diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1c9eaaa..3ba3af9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1 @@ -# CHANGE_ME - set correct code owner -* @linz/step-enablement \ No newline at end of file +* @linz/step-security \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d9204fa..2b0e406 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,16 +1,16 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - -version: 2 - -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: weekly - commit-message: - prefix: "fix(deps)" - cooldown: - default-days: 15 +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + commit-message: + prefix: "fix(deps)" + cooldown: + default-days: 15 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0df102f..9fa29ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,25 +1,41 @@ -name: CI -on: - pull_request: - branches: [master] - -jobs: - test: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - # CHANGE_ME - implement automation test for the actual action - - name: invoke action - uses: ./ - with: - input1: foo - input2: bar - - - name: Verify the result - run: | - source assert.sh - assert_eq "foo" "$DUMMY_INPUT1" - assert_eq "bar" "$DUMMY_INPUT2" +name: CI +on: + pull_request: + branches: [master] + +jobs: + build: + + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + + strategy: + matrix: + node-version: [18.x, 20.x, 22.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + id: setup-node + uses: ./ + with: + node-version: ${{ matrix.node-version }} + + - name: Check outputs + run: | + source assert.sh + assert_eq "$(node -v)" "${{ steps.setup-node.outputs.node-version }}" + + - name: Test Safe Chains + run: | + source assert.sh + set +e + npm install -g safe-chain-test + exitCode=$? + assert_eq "1" "$exitCode" + exit 0 + continue-on-error: true \ No newline at end of file diff --git a/.github/workflows/dependabot-automation.yml b/.github/workflows/dependabot-automation.yml index 65caa95..5deb943 100644 --- a/.github/workflows/dependabot-automation.yml +++ b/.github/workflows/dependabot-automation.yml @@ -1,30 +1,30 @@ -name: Dependabot automation - -on: pull_request - -permissions: - contents: write - pull-requests: write - -jobs: - dependabot: - runs-on: ubuntu-latest - if: github.actor == 'dependabot[bot]' - steps: - - name: Dependabot metadata - id: metadata - uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - name: Approve PR - run: gh pr review --approve "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.STEP_GITHUB_ACTION_TOKEN }} - - name: Enable auto-merge for Dependabot PRs that doesn't include major version update - if: steps.metadata.outputs.update-type != 'version-update:semver-major' - run: gh pr merge --auto --squash "$PR_URL" - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.STEP_GITHUB_ACTION_TOKEN }} - +name: Dependabot automation + +on: pull_request + +permissions: + contents: write + pull-requests: write + +jobs: + dependabot: + runs-on: ubuntu-latest + if: github.actor == 'dependabot[bot]' + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Approve PR + run: gh pr review --approve "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.STEP_GITHUB_ACTION_TOKEN }} + - name: Enable auto-merge for Dependabot PRs that doesn't include major version update + if: steps.metadata.outputs.update-type != 'version-update:semver-major' + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.STEP_GITHUB_ACTION_TOKEN }} + diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 4077efd..140a186 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -1,11 +1,11 @@ -name: "Lint PR" - -on: - pull_request: - types: ["opened", "edited", "reopened", "synchronize"] - -jobs: - pr-lint: - runs-on: ubuntu-latest - steps: +name: "Lint PR" + +on: + pull_request: + types: ["opened", "edited", "reopened", "synchronize"] + +jobs: + pr-lint: + runs-on: ubuntu-latest + steps: - uses: linz/action-pull-request-lint@7adb4bc59b59dc6e097de831c29a17c2c1338826 # v1.2.0 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cd7f008..36aea0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,19 +1,19 @@ -name: release-please - -on: - push: - branches: - - master - -permissions: - contents: write - pull-requests: write - -jobs: - release-please: - runs-on: ubuntu-latest - steps: - - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 - with: - release-type: simple +name: release-please + +on: + push: + branches: + - master + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + steps: + - uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0 + with: + release-type: simple token: ${{ secrets.STEP_GITHUB_ACTION_TOKEN }} \ No newline at end of file diff --git a/README.md b/README.md index d32c548..e43d05e 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,2 @@ -# template-github-action - -Template repo to kick start a composite Github action, providing the following features and configurations - -1. [Sample composite action](action.yaml) -2. [Sample CI workflow](.github/workflows/ci.yml) to test the sample action - - provided [assert.sh](assert.sh) to perform simple assertions in shell -3. [Repo setup script](setup_repo.sh) to configure the new repo -4. PR title linting to enforce that the PR titles follows [conventional commit standard](https://www.conventionalcommits.org/) -5. Configures dependabot to update any Github action dependencies -6. Dependabot automation workflow to automatically approve and squash merge dependabot PRs -7. Automated release with [release-please](https://github.com/googleapis/release-please-action) -8. Sample [CODEOWNERS](.github/CODEOWNERS) file - -## Template usage - -1. When creating a new repo - 1. Recommend to prefix the repo name with `action-`, e.g. `action-setup-playwright` - 2. Use the `Start with a template` option and select this repo as the template. - 3. Clone the new repo - 4. Make sure you have [Github CLI](https://github.com/cli/cli#installation) installed - 5. Open a bash terminal to the repo folder - 6. Run `./setup_repo.sh` to configure the repo settings. Note - this script self-deletes after successful run, commit - the deletion as the script would be no longer required. -2. Search for word `CHANGE_ME` and modify the code as needed. -3. Replace this README file with documentation for the new action. -4. Implement the new action and release it with release-please -5. Ask in Slack channel `#team-step-enablement` or `#help-github` to grant dependabot access to this new repo - 1. so that consumers of your new action can receive automated upgrades when new version is released - 2. this setting is at the bottom of this page https://github.com/organizations/linz/settings/security_analysis +# action-setup-node +This action wraps the [actions/setup-node](https://github.com/actions/setup-node) action and implements [Aikido Safe-Chain](https://github.com/AikidoSec/safe-chain) to fail install upon an attempt to install a malicious node package. Please refer to the [actions/setup-node](https://github.com/actions/setup-node) documentation as this action is a like-for-like replacement, however, in all instances please use `linz/action-setup-node` rather than `actions/setup-node`. \ No newline at end of file diff --git a/action.yaml b/action.yaml index 60e86eb..7c7c030 100644 --- a/action.yaml +++ b/action.yaml @@ -1,20 +1,64 @@ -# CHANGE_ME - implement the actual action -name: dummy composite action - -inputs: - input1: - description: value to set to DUMMY_INPUT1 environment variable - input2: - description: value to set to DUMMY_INPUT2 environment variable - -runs: - using: composite - steps: - - name: Dummy step 1 - shell: bash - env: - INPUT1: ${{ inputs.input1 }} - INPUT2: ${{ inputs.input2 }} - run: | - echo "DUMMY_INPUT1=$INPUT1" >> $GITHUB_ENV - echo "DUMMY_INPUT2=$INPUT2" >> $GITHUB_ENV +name: Setup node build environment +description: | + Configure Aikido Safe-Chain and Node environment +inputs: + node-version: + description: 'Version Spec of the version to use. Examples: 12.x, 10.15.1, >=10.15.0.' + node-version-file: + description: 'File containing the version Spec of the version to use. Examples: package.json, .nvmrc, .node-version, .tool-versions.' + architecture: + description: 'Target architecture for Node to use. Examples: x86, x64. Will use system architecture by default.' + check-latest: + description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec.' + default: false + registry-url: + description: 'Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, and set up auth to read in from env.NODE_AUTH_TOKEN.' + scope: + description: 'Optional scope for authenticating against scoped registries. Will fall back to the repository owner when using the GitHub Packages registry (https://npm.pkg.github.com/).' + token: + description: Used to pull node distributions from node-versions. Since there's a default, this is typically not supplied by the user. When running this action on github.com, the default value is sufficient. When running on GHES, you can pass a personal access token for github.com if you are experiencing rate limiting. + default: ${{ github.server_url == 'https://github.com' && github.token || '' }} + cache: + description: 'Used to specify a package manager for caching in the default directory. Supported values: npm, yarn, pnpm.' + package-manager-cache: + description: 'Set to false to disable automatic caching. By default, caching is enabled when either devEngines.packageManager or the top-level packageManager field in package.json specifies npm as the package manager.' + default: true + cache-dependency-path: + description: 'Used to specify the path to a dependency file: package-lock.json, yarn.lock, etc. Supports wildcards or a list of file names for caching multiple dependencies.' + mirror: + description: 'Used to specify an alternative mirror to downlooad Node.js binaries from' + mirror-token: + description: 'The token used as Authorization header when fetching from the mirror' +outputs: + cache-hit: + description: 'A boolean value to indicate if a cache was hit.' + value: ${{ steps.setup-node.outputs.cache-hit }} + node-version: + description: 'The installed node version.' + value: ${{ steps.setup-node.outputs.node-version }} + + +runs: + using: composite + steps: + - name: Setup Node.js + id: setup-node + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version: ${{ inputs.node-version }} + node-version-file: ${{ inputs.node-version-file }} + architecture: ${{ inputs.architecture }} + check-latest: ${{ inputs.check-latest }} + registry-url: ${{ inputs.registry-url }} + scope: ${{ inputs.scope }} + token: ${{ inputs.token }} + cache: ${{ inputs.cache }} + package-manager-cache: ${{ inputs.package-manager-cache }} + cache-dependency-path: ${{ inputs.cache-dependency-path }} + mirror: ${{ inputs.mirror }} + mirror-token: ${{ inputs.mirror-token }} + - name: Setup Aikido Safe-Chain + shell: bash + run: | + npm i -g @aikidosec/safe-chain + safe-chain setup-ci diff --git a/setup_repo.sh b/setup_repo.sh deleted file mode 100755 index 8c8c6ab..0000000 --- a/setup_repo.sh +++ /dev/null @@ -1,119 +0,0 @@ -#! /usr/bin/env bash -# This script sets up a GitHub repository with recommended settings. - -REPO_NAME_WITH_OWNER=$(gh repo view --json nameWithOwner -q '.nameWithOwner') - -read -p "Initialising repo setting for $REPO_NAME_WITH_OWNER. Continue (y/N)? " choice -case "$choice" in - y|Y ) echo "Proceeding...";; - * ) echo "Abort" && exit 1;; -esac - -echo "Configure basic repo settings..." -gh api \ - --silent \ - --method PATCH \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "/repos/$REPO_NAME_WITH_OWNER" \ - --input - <<< '{ - "has_wiki": false, - "allow_squash_merge": true, - "allow_merge_commit": false, - "allow_rebase_merge": false, - "allow_auto_merge": true, - "delete_branch_on_merge": true, - "use_squash_pr_title_as_default": true, - "squash_merge_commit_title": "PR_TITLE", - "squash_merge_commit_message": "PR_BODY" -}' - -echo "Enable Dependabot alerts..." -gh api \ - --method PUT \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "/repos/$REPO_NAME_WITH_OWNER/vulnerability-alerts" - -echo "Enable Dependabot security updates..." -gh api \ - --method PUT \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "/repos/$REPO_NAME_WITH_OWNER/automated-security-fixes" - -echo "Allow action in this repo to be accessible from repositories in the 'linz' organization..." -gh api \ - --method PUT \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "/repos/$REPO_NAME_WITH_OWNER/actions/permissions/access" \ - --input - <<< '{ - "access_level": "organization" -}' - -if gh ruleset list | grep --quiet "Default branch"; then - echo "Default branch ruleset already exists." -else - echo "Setup ruleset to protect default branch..." - # note - "integration_id": 15368 is 'Github Actions' - gh api \ - --method POST \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "/repos/$REPO_NAME_WITH_OWNER/rulesets" \ - --input - <<< '{ - "name": "Default branch", - "target": "branch", - "enforcement": "active", - "conditions": { - "ref_name": { - "include": [ - "~DEFAULT_BRANCH" - ], - "exclude": [] - } - }, - "rules": [ - { - "type": "deletion" - }, - { - "type": "non_fast_forward" - }, - { - "type": "pull_request", - "parameters": { - "allowed_merge_methods": ["squash"], - "dismiss_stale_reviews_on_push": true, - "require_code_owner_review": true, - "require_last_push_approval": true, - "required_approving_review_count": 1, - "required_review_thread_resolution": false - } - }, - { - "type": "required_status_checks", - "parameters": { - "strict_required_status_checks_policy": false, - "required_status_checks": [ - { - "context": "test", - "integration_id": 15368 - }, - { - "context": "pr-lint", - "integration_id": 15368 - } - ] - } - } - ] -}' -fi - -echo "✅ Repo settings applied." - -me=$(basename "$0") -rm "$me" -echo "✅ Deleted $me, you can commit this change to the repo as the script is no longer needed." \ No newline at end of file