From 25f68feffda9db24a274ff4d84227a3efd735e48 Mon Sep 17 00:00:00 2001 From: arnavchachra Date: Fri, 24 Jul 2026 20:02:09 +0530 Subject: [PATCH] =?UTF-8?q?feat(build,deploy):=20switch=20build=E2=86=92de?= =?UTF-8?q?ploy=20handoff=20from=20artifacts=20to=20Actions=20cache?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build gains `output: cache`, which saves `build-output-path` under a caller- supplied `cache-key` via actions/cache/save. deploy gains `restore-cache`, which restores it via actions/cache/restore using an exact-key match and fails the deploy on a cache miss -- so an evicted or missing cache is a loud failure, never a silent empty deploy. Callers pass a run-unique `cache-key` (e.g. including github.run_id) to both sides. The artifact handoff is removed. This sidesteps the Actions artifact storage quota, whose exhaustion fails the build's upload step even when the build itself succeeds. BREAKING CHANGE: build no longer supports `output: artifact`, `artifact-name`, or `artifact-retention-days`, and deploy no longer supports `download-artifact` or `artifact-name`. Callers using the artifact handoff must switch to the cache handoff: set `output: cache` + `cache-key` on build, and `restore-cache: "true"` + a matching `cache-key` on deploy. --- README.md | 13 ++++++++-- actions/build/action.yml | 37 ++++++++++++++++------------ actions/deploy/action.yml | 51 +++++++++++++++++++++++++++------------ 3 files changed, 68 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 8cb76d8..ea66281 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,8 @@ jobs: - uses: nurdsoft/ci-workflows/actions/build@v2 with: run: # or rely on `make build` - output: artifact + output: cache + cache-key: build-${{ github.sha }}-${{ github.run_id }} deploy: needs: [build] @@ -70,11 +71,19 @@ jobs: - uses: nurdsoft/ci-workflows/actions/deploy@v2 with: run: # or rely on `make deploy` - download-artifact: "true" + restore-cache: "true" + cache-key: build-${{ github.sha }}-${{ github.run_id }} gcp-wif-provider: ${{ secrets.WIF_PROVIDER }} gcp-service-account: ${{ secrets.SERVICE_ACCOUNT }} ``` +The build output is handed to deploy through the Actions cache: `build` saves +`build-output-path` under `cache-key`, and `deploy` restores it. Pass the same +**run-unique** `cache-key` to both (include `github.run_id` so re-runs and +concurrent runs don't collide). The restore is an exact-key match and fails the +deploy on a miss, so an evicted or missing cache surfaces as a loud failure +rather than a silent empty deploy. + **App pipeline — Docker + Cloud Run (release, build, deploy)** Activated by passing `image-name` to `build` and `cloudrun-service` to `deploy`. The static-build and static-deploy steps are skipped automatically — existing callers are unaffected. diff --git a/actions/build/action.yml b/actions/build/action.yml index f3225a4..1dfb061 100644 --- a/actions/build/action.yml +++ b/actions/build/action.yml @@ -1,9 +1,16 @@ name: Build description: >- - Produce a deployable artifact. Runs `run` if given, otherwise ` build` + Produce a deployable build. Runs `run` if given, otherwise ` build` (default make) -- so no Makefile is required when `run` is supplied. Optionally prepares a Node/Expo toolchain and authenticates to a cloud (for registry - pushes performed by the build command). Can upload the output as an artifact. + pushes performed by the build command). Can hand the output to the deploy job + via the Actions cache (output: cache). + + Cache handoff: output: cache saves the build output under a caller-supplied + cache-key. The key must be unique per run (e.g. include github.run_id) and + match the deploy side; deploy restores it with an exact-key lookup and fails on + a miss, so a cache eviction surfaces as a loud failure rather than a silent + empty deploy. Docker path: when `image-name` is set the action switches to a Docker build+push flow -- authenticates via WIF, optionally fetches build-time env vars from Secret @@ -45,21 +52,20 @@ inputs: required: false default: "" output: - description: "Artifact handling: artifact | none." + description: "Output handling: cache | none." required: false default: none - artifact-name: - description: Name of the uploaded artifact (when output is artifact). - required: false - default: build-output build-output-path: - description: Directory uploaded as the artifact. + description: Directory saved to the cache (when output is cache). required: false default: out - artifact-retention-days: - description: Artifact retention. + cache-key: + description: >- + Cache key for the build output when output is cache. Must be unique per + run (e.g. include github.sha and github.run_id) and match the deploy + side's cache-key. Required when output is cache. required: false - default: "7" + default: "" # -- Shared cloud auth inputs ----------------------------------------------- gcp-wif-provider: @@ -171,13 +177,12 @@ runs: $RUNNER build ENV="$ENV" fi - - name: Upload artifact - if: inputs.output == 'artifact' && inputs.image-name == '' && inputs.ghcr-image == '' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + - name: Save build cache + if: inputs.output == 'cache' && inputs.image-name == '' && inputs.ghcr-image == '' + uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: - name: ${{ inputs.artifact-name }} path: ${{ inputs.build-output-path }} - retention-days: ${{ inputs.artifact-retention-days }} + key: ${{ inputs.cache-key }} # -- Docker build path ----------------------------------------------------- - name: Configure Docker for Artifact Registry (build path) diff --git a/actions/deploy/action.yml b/actions/deploy/action.yml index 1762895..fbd1c19 100644 --- a/actions/deploy/action.yml +++ b/actions/deploy/action.yml @@ -1,8 +1,14 @@ name: Deploy description: >- Ship the build. Runs `run` if given, otherwise ` deploy` (default make) - -- no Makefile required when `run` is supplied. Optionally downloads a build - artifact, prepares a Node/Expo toolchain, and authenticates to a cloud. + -- no Makefile required when `run` is supplied. Optionally restores the build + output from the Actions cache (restore-cache), prepares a Node/Expo toolchain, + and authenticates to a cloud. + + Cache restore: restore-cache pairs with the build action's output: cache. It + restores build-output-path using an exact cache-key match and fails the deploy + on a cache miss, so an evicted or missing cache never results in a silent empty + deploy. cache-key must match the build side. Cloud Run service path: when `cloudrun-service` is set the action switches to a Cloud Run service deploy flow -- authenticates via WIF, optionally fetches runtime @@ -35,18 +41,23 @@ inputs: description: Expo token, forwarded to setup for EAS submit/update. required: false default: "" - download-artifact: - description: Download a build artifact before deploying. - required: false - default: "false" - artifact-name: - description: Artifact to download. - required: false - default: build-output build-output-path: - description: Local path the artifact is unpacked to. + description: Local path the cache is restored to. required: false default: out + restore-cache: + description: >- + Restore the build output from the Actions cache before deploying. + Fails the deploy on a cache miss. + required: false + default: "false" + cache-key: + description: >- + Cache key to restore the build output from when restore-cache is true. + Restored with an exact-key match and must equal the build side's cache-key; + a miss fails the deploy. Required when restore-cache is true. + required: false + default: "" # -- Shared cloud auth inputs ----------------------------------------------- gcp-wif-provider: @@ -130,12 +141,22 @@ runs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # -- Static path ----------------------------------------------------------- - - name: Download artifact - if: inputs.download-artifact == 'true' && inputs.cloudrun-service == '' && inputs.cloudrun-job == '' - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + - name: Restore build cache + id: restore-cache + if: inputs.restore-cache == 'true' && inputs.cloudrun-service == '' && inputs.cloudrun-job == '' + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: - name: ${{ inputs.artifact-name }} path: ${{ inputs.build-output-path }} + key: ${{ inputs.cache-key }} + + - name: Fail on build cache miss + if: inputs.restore-cache == 'true' && inputs.cloudrun-service == '' && inputs.cloudrun-job == '' && steps.restore-cache.outputs.cache-hit != 'true' + shell: bash + env: + CACHE_KEY: ${{ inputs.cache-key }} + run: | + echo "ERROR: build cache '$CACHE_KEY' not found — refusing to deploy a missing build." >&2 + exit 1 - name: Setup toolchain if: inputs.node-version != '' && inputs.cloudrun-service == '' && inputs.cloudrun-job == ''