diff --git a/.github/workflows/promote-release-candidate.yaml b/.github/workflows/promote-release-candidate.yaml deleted file mode 100644 index 2e55892..0000000 --- a/.github/workflows/promote-release-candidate.yaml +++ /dev/null @@ -1,202 +0,0 @@ -name: Promote Release Candidate -on: - workflow_call: - inputs: - source_tag: - description: "Source -main.N tag to promote (blank = latest -main.N tag in the repo)" - required: false - default: "" - type: string - image_tag_prefixes: - description: "JSON array of image tag prefixes to retag (e.g. '[\"\", \"nginx-\"]'). Use an empty string for the base image." - required: true - type: string - registry: - description: "Docker registry hosting the images" - required: false - default: "ghcr.io" - type: string - target_branch: - description: "Branch to reset to the source tag's commit (used as the release candidate branch)" - required: false - default: "rc" - type: string - additional_image_refs: - description: > - JSON array of full image references (with `{tag}` placeholder) to - retag in addition to the `image_tag_prefixes` above. Use this for - images that don't live at the caller repo's own registry path — for - example, `-profiler` variants published to a separate image name. - Example: '["ghcr.io/owner/repo-profiler:{tag}"]' - required: false - default: "[]" - type: string - sync_cdn_assets: - description: > - If true, sync the repo's CDN assets from the source tag path to the - pretty tag path under `s3:////`. Required when - the caller's Build workflow uploads tag-versioned JS/CSS assets to - S3 (e.g. webstore, checkout, manage), so promoted deployments can - resolve the same assets at the new pretty tag path. - required: false - default: false - type: boolean - secrets: - repo_write_pat: - description: "PAT with contents:write for force-pushing the target branch and pushing tags" - required: true - gh_token: - description: "PAT with packages:write on the caller repo's container registry (used to retag images)" - required: true - cdn_bucket: - description: "S3 bucket name holding the caller's CDN assets. Required only when sync_cdn_assets=true." - required: false - cdn_aws_access_id: - description: "AWS access key for the CDN bucket. Required only when sync_cdn_assets=true." - required: false - cdn_aws_access_secret: - description: "AWS secret key for the CDN bucket. Required only when sync_cdn_assets=true." - required: false - outputs: - source_tag: - description: "The -main.N tag that was promoted" - value: ${{ jobs.promote.outputs.source_tag }} - pretty_tag: - description: "The promoted pretty (release) tag" - value: ${{ jobs.promote.outputs.pretty_tag }} - -jobs: - promote: - runs-on: ubuntu-latest - outputs: - source_tag: ${{ steps.resolve.outputs.source_tag }} - pretty_tag: ${{ steps.compute.outputs.pretty_tag }} - steps: - - name: Checkout - uses: actions/checkout@v6 - with: - fetch-depth: 0 - token: ${{ secrets.repo_write_pat }} - - name: Resolve source tag - id: resolve - env: - INPUT_TAG: ${{ inputs.source_tag }} - run: | - if [ -n "$INPUT_TAG" ]; then - TAG="$INPUT_TAG" - else - TAG=$(git tag --sort=-creatordate --list '*-main.*' | head -n1) - if [ -z "$TAG" ]; then - echo "::error::No -main.N tag found in this repo" - exit 1 - fi - fi - # '^{commit}' dereferences annotated tags to their target commit; - # for lightweight tags this is a no-op. Branch refs must point to - # commits, not tag objects, so the commit SHA is what we push. - if ! SHA=$(git rev-parse "$TAG^{commit}" 2>/dev/null); then - echo "::error::Tag '$TAG' does not exist" - exit 1 - fi - echo "source_tag=$TAG" >> "$GITHUB_OUTPUT" - echo "source_sha=$SHA" >> "$GITHUB_OUTPUT" - echo "Resolved source tag: $TAG ($SHA)" - - name: Compute pretty version - id: compute - env: - SRC: ${{ steps.resolve.outputs.source_tag }} - run: | - PRETTY="${SRC%-main.*}" - if [ "$PRETTY" = "$SRC" ]; then - echo "::error::Source tag '$SRC' doesn't match '*-main.N' pattern. Pass a -main.N tag via source_tag, or leave blank to use the latest." - exit 1 - fi - if git rev-parse "$PRETTY" >/dev/null 2>&1; then - { - echo "## Release Candidate promotion blocked" - echo "" - echo "Pretty tag \`$PRETTY\` already exists — source \`$SRC\` has already been promoted." - echo "" - echo "### What to do" - echo "- **New changes on \`main\`?** Wait for the Build workflow to produce a fresh \`-main.N\` tag, then re-run." - echo "- **Need to redeploy the existing RC to QA?** Run the \`QA EKS Deploy\` workflow with \`image_tag=$PRETTY\`." - echo "- **Want to promote a specific \`-main.N\` tag?** Re-run and set \`source_tag\` explicitly." - } >> "$GITHUB_STEP_SUMMARY" - echo "::error::Pretty tag '$PRETTY' already exists (source '$SRC' has already been promoted). See job summary for next steps." - exit 1 - fi - echo "pretty_tag=$PRETTY" >> "$GITHUB_OUTPUT" - echo "Pretty tag: $PRETTY" - - name: Configure git - run: | - git config user.name github-actions - git config user.email github-actions@github.com - - name: Reset target branch to source commit - env: - SHA: ${{ steps.resolve.outputs.source_sha }} - TARGET: ${{ inputs.target_branch }} - run: | - git push origin "+$SHA:refs/heads/$TARGET" - - name: Login to container registry - uses: docker/login-action@v3 - with: - registry: ${{ inputs.registry }} - username: ${{ github.actor }} - password: ${{ secrets.gh_token }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Retag docker images - env: - REGISTRY: ${{ inputs.registry }} - IMAGE_NAME: ${{ github.repository }} - SRC: ${{ steps.resolve.outputs.source_tag }} - PRETTY: ${{ steps.compute.outputs.pretty_tag }} - PREFIXES_JSON: ${{ inputs.image_tag_prefixes }} - ADDITIONAL_JSON: ${{ inputs.additional_image_refs }} - run: | - count=$(echo "$PREFIXES_JSON" | jq 'length') - if [ "$count" -eq 0 ]; then - echo "::error::image_tag_prefixes must not be empty" - exit 1 - fi - echo "$PREFIXES_JSON" | jq -r '.[]' | while IFS= read -r prefix; do - echo "Retagging ${prefix}${SRC} -> ${prefix}${PRETTY}" - docker buildx imagetools create \ - --tag "$REGISTRY/$IMAGE_NAME:${prefix}${PRETTY}" \ - "$REGISTRY/$IMAGE_NAME:${prefix}${SRC}" - done - echo "$ADDITIONAL_JSON" | jq -r '.[]' | while IFS= read -r template; do - [ -z "$template" ] && continue - src_ref="${template//\{tag\}/$SRC}" - dst_ref="${template//\{tag\}/$PRETTY}" - echo "Retagging (additional) $src_ref -> $dst_ref" - docker buildx imagetools create --tag "$dst_ref" "$src_ref" - done - - name: Sync CDN assets - if: inputs.sync_cdn_assets - env: - BUCKET: ${{ secrets.cdn_bucket }} - REPO_NAME: ${{ github.event.repository.name }} - SRC: ${{ steps.resolve.outputs.source_tag }} - PRETTY: ${{ steps.compute.outputs.pretty_tag }} - AWS_ACCESS_KEY_ID: ${{ secrets.cdn_aws_access_id }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.cdn_aws_access_secret }} - AWS_DEFAULT_REGION: us-east-1 - run: | - if [ -z "$BUCKET" ] || [ -z "$AWS_ACCESS_KEY_ID" ] || [ -z "$AWS_SECRET_ACCESS_KEY" ]; then - echo "::error::sync_cdn_assets=true requires cdn_bucket, cdn_aws_access_id, and cdn_aws_access_secret secrets." - exit 1 - fi - SRC_PATH="s3://${BUCKET}/${REPO_NAME}/${SRC}/" - DST_PATH="s3://${BUCKET}/${REPO_NAME}/${PRETTY}/" - echo "Syncing CDN assets ${SRC_PATH} -> ${DST_PATH}" - aws s3 sync "$SRC_PATH" "$DST_PATH" - - name: Create pretty tag and GitHub release - uses: ncipollo/release-action@v1 - with: - token: ${{ secrets.repo_write_pat }} - tag: ${{ steps.compute.outputs.pretty_tag }} - commit: ${{ steps.resolve.outputs.source_sha }} - name: Release Candidate ${{ steps.compute.outputs.pretty_tag }} - body: "Promoted from `${{ steps.resolve.outputs.source_tag }}`." - prerelease: true