From 12c3dceb7310e5ecf6eae73d73990bb7b7678ad0 Mon Sep 17 00:00:00 2001 From: sebasnallar Date: Tue, 25 Aug 2026 13:26:44 -0300 Subject: [PATCH 1/2] ci: chain publish + artifact registration into the release run The tag-push publish workflow never fired on release: release-please creates tags with GITHUB_TOKEN and GitHub does not trigger workflows from bot-token events. The manual delete/re-push workaround flipped the affected releases (v0.3.0, v0.3.1) into Draft state. Adopt actions-nullplatform's release-publish-oci: release-please, docker build+push to ECR, np artifact registration, and release finalize (artifact metadata appended to the body, release force- published) all chained in one run. publish-image.yml becomes a workflow_dispatch-only fallback for backfilling existing tags. Co-Authored-By: Claude Fable 5 --- .github/workflows/publish-image.yml | 18 ++++++++++++------ .github/workflows/release.yml | 22 ++++++++++++++++++++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index a93c4f9..fc019a4 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -1,11 +1,17 @@ name: publish-image -# Publishes the scope image to ECR Public on every semver tag (created by the -# release workflow). Result: public.ecr.aws/nullplatform/scopes/lambda: +# MANUAL fallback: republish the scope image for an EXISTING tag (backfill an +# old release, recover from a failed publish). The normal path is release.yml, +# which builds and publishes in the same run release-please cuts the release — +# a tag-push trigger would never fire there anyway (tags are created by the +# GitHub Actions bot token, whose events do not trigger workflows). on: - push: - tags: - - 'v*' + workflow_dispatch: + inputs: + tag: + description: 'Existing git tag to build and publish (e.g. v0.3.1)' + required: true + type: string permissions: id-token: write # required for OIDC auth against AWS @@ -17,7 +23,7 @@ jobs: with: image_name: scopes/lambda context: . - tag: ${{ github.ref_name }} + tag: ${{ inputs.tag }} secrets: aws_role_arn: ${{ secrets.AWS_ROLE_ARN_ECR_PUSH }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a65e73..039fc17 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,15 @@ name: release +# Full release pipeline in ONE chained run: release-please -> docker build+push +# to ECR Public -> np artifact registration -> release finalized with the +# artifact metadata (image, digest, pinned reference, artifact id) and +# force-published. +# +# Chained on purpose: release-please creates tags with GITHUB_TOKEN, and +# GitHub never triggers workflows from bot-token events — a separate +# `on: push: tags` publish workflow does not fire (and the delete/re-push +# workaround flips the release to Draft). publish-image.yml remains as a +# manual (workflow_dispatch) fallback for backfilling old tags. on: push: branches: @@ -8,8 +18,16 @@ on: permissions: contents: write pull-requests: write + id-token: write # OIDC auth against AWS for the ECR push jobs: release: - uses: nullplatform/actions-nullplatform/.github/workflows/release.yml@main - secrets: inherit + uses: nullplatform/actions-nullplatform/.github/workflows/release-publish-oci.yml@main + with: + image_name: scopes/lambda + # Same behavior as the previous release.yml caller (shared defaults). + release-type: terraform-module + update_readme_versions: true + secrets: + aws_role_arn: ${{ secrets.AWS_ROLE_ARN_ECR_PUSH }} + artifact_np_api_key: ${{ secrets.ARTIFACT_NP_API_KEY }} From f3fe1b441290247404f2d37a896278c2efa0b72e Mon Sep 17 00:00:00 2001 From: sebasnallar Date: Wed, 26 Aug 2026 09:34:05 -0300 Subject: [PATCH 2/2] ci: use existing_tag recovery mode instead of a separate fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit release-publish-oci now accepts existing_tag (skip release-please, publish + finalize an already-created tag), which covers everything publish-image.yml's manual fallback did — and also writes the artifact metadata into the release, which the fallback never did. One workflow, one path; workflow_dispatch exposes the recovery mode. Co-Authored-By: Claude Fable 5 --- .github/workflows/publish-image.yml | 57 ----------------------------- .github/workflows/release.yml | 14 ++++++- 2 files changed, 12 insertions(+), 59 deletions(-) delete mode 100644 .github/workflows/publish-image.yml diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml deleted file mode 100644 index fc019a4..0000000 --- a/.github/workflows/publish-image.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: publish-image - -# MANUAL fallback: republish the scope image for an EXISTING tag (backfill an -# old release, recover from a failed publish). The normal path is release.yml, -# which builds and publishes in the same run release-please cuts the release — -# a tag-push trigger would never fire there anyway (tags are created by the -# GitHub Actions bot token, whose events do not trigger workflows). -on: - workflow_dispatch: - inputs: - tag: - description: 'Existing git tag to build and publish (e.g. v0.3.1)' - required: true - type: string - -permissions: - id-token: write # required for OIDC auth against AWS - contents: read - -jobs: - publish: - uses: nullplatform/actions-nullplatform/.github/workflows/docker-build-push-ecr.yml@main - with: - image_name: scopes/lambda - context: . - tag: ${{ inputs.tag }} - secrets: - aws_role_arn: ${{ secrets.AWS_ROLE_ARN_ECR_PUSH }} - - # Register the pushed image as a platform artifact, pinned by its digest and - # visible to every organization — so `np package publish` / scope_definition - # can resolve it. Idempotent upsert: re-runs of the same digest return the - # same ids. - publish-artifact: - name: Register oci_image artifact - needs: publish - runs-on: ubuntu-24.04 - env: - # np reads the key from NULLPLATFORM_API_KEY; supply it via the - # ARTIFACT_NP_API_KEY repository secret. - NULLPLATFORM_API_KEY: ${{ secrets.ARTIFACT_NP_API_KEY }} - # Owner NRN for the artifact (repository/organization variable). Making it - # globally visible additionally requires artifact permissions org-wide. - NP_ARTIFACT_NRN: ${{ vars.NP_ARTIFACT_NRN }} - steps: - - name: Install np CLI (alpha-packages build) - run: curl -s https://cli.nullplatform.com/install.sh | VERSION=alpha-packages sh - - - name: Register scopes-lambda image artifact (visible to everyone) - run: | - np artifact create \ - --nrn "$NP_ARTIFACT_NRN" \ - --type oci_image \ - --registry public.ecr.aws \ - --repository nullplatform/scopes/lambda \ - --digest "${{ needs.publish.outputs.image_digest }}" \ - --visible-to "organization=*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 039fc17..5057b35 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,12 +8,21 @@ name: release # Chained on purpose: release-please creates tags with GITHUB_TOKEN, and # GitHub never triggers workflows from bot-token events — a separate # `on: push: tags` publish workflow does not fire (and the delete/re-push -# workaround flips the release to Draft). publish-image.yml remains as a -# manual (workflow_dispatch) fallback for backfilling old tags. +# workaround flips the release to Draft). +# +# Recovery / backfill: run this workflow manually with existing_tag to +# publish + finalize a tag that already exists (a release whose publish +# failed, or a pre-pipeline tag with no artifact metadata). on: push: branches: - main + workflow_dispatch: + inputs: + existing_tag: + description: 'Publish + finalize an existing tag (recovery/backfill)' + required: true + type: string permissions: contents: write @@ -28,6 +37,7 @@ jobs: # Same behavior as the previous release.yml caller (shared defaults). release-type: terraform-module update_readme_versions: true + existing_tag: ${{ inputs.existing_tag || '' }} secrets: aws_role_arn: ${{ secrets.AWS_ROLE_ARN_ECR_PUSH }} artifact_np_api_key: ${{ secrets.ARTIFACT_NP_API_KEY }}