diff --git a/.github/workflows/actions-lint.yaml b/.github/workflows/actions-lint.yaml index 391d8bf..f30a1c6 100644 --- a/.github/workflows/actions-lint.yaml +++ b/.github/workflows/actions-lint.yaml @@ -31,7 +31,11 @@ env: jobs: actionlint: name: actionlint and shellcheck - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-actionlint-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: @@ -60,7 +64,11 @@ jobs: zizmor: name: zizmor - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-zizmor-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: diff --git a/.github/workflows/e2e-nightly.yaml b/.github/workflows/e2e-nightly.yaml index a8e5ae4..bb51be8 100644 --- a/.github/workflows/e2e-nightly.yaml +++ b/.github/workflows/e2e-nightly.yaml @@ -18,7 +18,7 @@ env: jobs: functions: name: Functions and optional components - runs-on: ubuntu-latest + runs-on: ${{ format('gcrunner={0}-functions-{1}/machine=c3d-standard-8', github.run_id, strategy.job-index) }} timeout-minutes: 60 steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 7aa7c6e..9fcd047 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -23,7 +23,11 @@ env: jobs: lint: name: Lint (Helm ${{ matrix.helm }}) - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-lint-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} strategy: fail-fast: false matrix: @@ -58,7 +62,11 @@ jobs: unittest: name: Unit tests (Helm ${{ matrix.helm }}) - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-unittest-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} strategy: fail-fast: false matrix: @@ -96,7 +104,11 @@ jobs: kubeconform: name: kubeconform - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-kubeconform-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: @@ -118,7 +130,11 @@ jobs: generated: name: Generated files are up to date - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-generated-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: @@ -139,7 +155,11 @@ jobs: metadata: name: Chart metadata - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-metadata-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: @@ -152,10 +172,16 @@ jobs: artifacthub: name: Artifact Hub lint - runs-on: ubuntu-latest - container: - image: docker.io/artifacthub/ah:v1.23.0@sha256:e5d2a2cdef85aac4928e8176ffaad24746c5fe961d64ff6856f7222957095356 - options: --user 1001 + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-artifacthub-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} + env: + # Run from the image, pinned by digest, with the runner's own uid: as a + # job container, its user has to match the runner's to write the + # runner's files, and that uid differs between runners. + AH_IMAGE: docker.io/artifacthub/ah:v1.23.0@sha256:e5d2a2cdef85aac4928e8176ffaad24746c5fe961d64ff6856f7222957095356 steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: @@ -164,12 +190,15 @@ jobs: with: persist-credentials: false - name: ah lint - working-directory: charts - run: ah lint + run: docker run --rm -u "$(id -u):$(id -g)" -v "${GITHUB_WORKSPACE}/charts:/charts:ro" -w /charts "$AH_IMAGE" ah lint changelog: name: Changelog - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-changelog-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 with: diff --git a/.github/workflows/renovate-generate.yaml b/.github/workflows/renovate-generate.yaml index 42bee1a..8ee18aa 100644 --- a/.github/workflows/renovate-generate.yaml +++ b/.github/workflows/renovate-generate.yaml @@ -32,7 +32,11 @@ jobs: # The pull request's author, which a later pusher can't change. Forks # never get here: Renovate pushes branches to this repository. if: github.event.pull_request.user.login == 'renovate[bot]' && github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-generate-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} permissions: contents: read steps: diff --git a/.github/workflows/security-scan.yaml b/.github/workflows/security-scan.yaml index 9500097..de6117a 100644 --- a/.github/workflows/security-scan.yaml +++ b/.github/workflows/security-scan.yaml @@ -19,7 +19,7 @@ env: jobs: prepare: name: Images and visibility - runs-on: ubuntu-latest + runs-on: ${{ format('gcrunner={0}-prepare-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) }} outputs: images: ${{ steps.images.outputs.images }} public: ${{ steps.repo.outputs.public }} @@ -49,7 +49,7 @@ jobs: images: name: Image ${{ matrix.image.name }} needs: prepare - runs-on: ubuntu-latest + runs-on: ${{ format('gcrunner={0}-images-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) }} permissions: contents: read security-events: write @@ -86,7 +86,7 @@ jobs: config: name: Rendered manifests needs: prepare - runs-on: ubuntu-latest + runs-on: ${{ format('gcrunner={0}-config-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) }} permissions: contents: read security-events: write diff --git a/.github/workflows/test-install.yaml b/.github/workflows/test-install.yaml index 9d1166f..33d3374 100644 --- a/.github/workflows/test-install.yaml +++ b/.github/workflows/test-install.yaml @@ -30,7 +30,11 @@ concurrency: jobs: install: name: ${{ matrix.scenario }} (k8s ${{ matrix.kubernetes }})${{ matrix.upgrade-from && format(' upgrade from {0}', matrix.upgrade-from) || '' }} - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-install-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} timeout-minutes: 45 strategy: fail-fast: false @@ -168,7 +172,11 @@ jobs: name: Install result needs: install if: always() - runs-on: ubuntu-latest + runs-on: >- + ${{ (github.event_name != 'pull_request' + || github.event.pull_request.head.repo.full_name == github.repository) + && format('gcrunner={0}-result-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) + || 'ubuntu-latest' }} permissions: {} steps: - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 diff --git a/.github/workflows/upstream-drift.yaml b/.github/workflows/upstream-drift.yaml index f1f4939..aa1d5f8 100644 --- a/.github/workflows/upstream-drift.yaml +++ b/.github/workflows/upstream-drift.yaml @@ -12,7 +12,7 @@ permissions: jobs: check: - runs-on: ubuntu-latest + runs-on: ${{ format('gcrunner={0}-check-{1}/machine=c3d-standard-4', github.run_id, strategy.job-index) }} permissions: contents: read issues: write # open the drift issue diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 34d9a40..2db945b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -105,6 +105,20 @@ The scenarios CI installs are the `charts/appwrite/ci/*-values.yaml` files. | [Upstream drift](.github/workflows/upstream-drift.yaml) | weekly | opens an issue when Appwrite releases a version the chart doesn't ship | | [Release](.github/workflows/release.yaml) | `Chart.yaml` changes on `main` | see [RELEASING.md](RELEASING.md) | +Jobs run on Appwrite's [gcrunner](https://github.com/appwrite-labs/gcrunner) +runners: an ephemeral Compute Engine VM per job, picked with +`runs-on: gcrunner=--/machine=` (c3d-standard-8 +for the nightly, c3d-standard-4 otherwise). Pull requests from forks ask for +GitHub-hosted runners instead. That isn't a security boundary: a pull request +runs its own copy of the workflow, so a fork can ask for gcrunner, and +gcrunner doesn't check where a job comes from. While the repository is +public, the guard is that a maintainer approves every workflow run from a +fork pull request (Settings → Actions → General → "Require approval for all +external contributors") after reading its workflow changes; never approve a +fork's run that changes `runs-on`. Release and Scorecard stay on GitHub-hosted +runners: Scorecard only publishes results from them, and the release's +signature and provenance attestation name the runner that built the chart. + Workflows pin every action to a commit SHA (with the version in a comment) and every tool to a version in `env:`, which Renovate updates through the custom managers in `renovate.json`. A new pinned tool needs a manager there. diff --git a/renovate.json b/renovate.json index 6ffa8c9..f916682 100644 --- a/renovate.json +++ b/renovate.json @@ -204,13 +204,13 @@ "extractVersionTemplate": "^v(?.*)$" }, { - "description": "Trivy image (tag and digest) in the security scan workflow", + "description": "Images run with docker run in the workflows (tag and digest): Trivy and Artifact Hub's ah", "customType": "regex", "managerFilePatterns": [ "/^\\.github/workflows/.+\\.ya?ml$/" ], "matchStrings": [ - "TRIVY_IMAGE:\\s*(?[^:\\s]+):(?[^@\\s]+)@(?sha256:[a-f0-9]{64})" + "(?:TRIVY|AH)_IMAGE:\\s*(?[^:\\s]+):(?[^@\\s]+)@(?sha256:[a-f0-9]{64})" ], "datasourceTemplate": "docker" }