-
Notifications
You must be signed in to change notification settings - Fork 6
153 lines (141 loc) · 5.98 KB
/
Copy pathpromote-release.yml
File metadata and controls
153 lines (141 loc) · 5.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# ABOUTME: Promotes an existing prerelease image from staging ECR to production ECR by re-tagging
# ABOUTME: (no rebuild — preserves byte digest) and creates a non-prerelease GitHub release.
name: Promote Release
on:
workflow_dispatch:
inputs:
prerelease_tag:
description: "Prerelease tag to promote (e.g., v1.2.3-rc.1)"
required: true
type: string
release_version:
description: "Release version to publish (e.g., v1.2.3)"
required: true
type: string
permissions:
id-token: write
contents: write
concurrency:
group: promote-release-${{ inputs.release_version }}
cancel-in-progress: false
jobs:
promote:
runs-on: ubuntu-latest
steps:
- name: Validate input formats and base-version match
env:
PRERELEASE_TAG: ${{ inputs.prerelease_tag }}
RELEASE_VERSION: ${{ inputs.release_version }}
run: |
if [[ ! "$PRERELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc\.[0-9]+$ ]]; then
echo "::error::Invalid prerelease_tag '$PRERELEASE_TAG'. Expected vMAJOR.MINOR.PATCH-rc.N."
exit 1
fi
if [[ ! "$RELEASE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::Invalid release_version '$RELEASE_VERSION'. Expected vMAJOR.MINOR.PATCH."
exit 1
fi
BASE="${PRERELEASE_TAG%-rc.*}"
if [[ "$BASE" != "$RELEASE_VERSION" ]]; then
echo "::error::Base version mismatch: prerelease '$PRERELEASE_TAG' (base: $BASE) does not match release '$RELEASE_VERSION'."
exit 1
fi
echo "Inputs OK: $PRERELEASE_TAG -> $RELEASE_VERSION"
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Verify prerelease GitHub release exists
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PRERELEASE_TAG: ${{ inputs.prerelease_tag }}
run: |
if ! IS_PRE=$(gh release view "$PRERELEASE_TAG" --json isPrerelease --jq '.isPrerelease' 2>/dev/null); then
echo "::error::GitHub release '$PRERELEASE_TAG' not found."
exit 1
fi
if [[ "$IS_PRE" != "true" ]]; then
echo "::error::GitHub release '$PRERELEASE_TAG' exists but is not a prerelease."
exit 1
fi
- name: Verify release_version does not already exist
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_VERSION: ${{ inputs.release_version }}
run: |
if gh release view "$RELEASE_VERSION" >/dev/null 2>&1; then
echo "::error::GitHub release '$RELEASE_VERSION' already exists."
exit 1
fi
if git ls-remote --tags origin "refs/tags/$RELEASE_VERSION" | grep -q .; then
echo "::error::Tag '$RELEASE_VERSION' already exists on origin."
exit 1
fi
echo "Release version '$RELEASE_VERSION' is available."
- name: Resolve commit SHA from prerelease tag
id: resolve_sha
env:
PRERELEASE_TAG: ${{ inputs.prerelease_tag }}
run: |
SHA=$(git rev-list -n1 "$PRERELEASE_TAG")
if [[ -z "$SHA" ]]; then
echo "::error::Could not resolve commit SHA for tag '$PRERELEASE_TAG'."
exit 1
fi
echo "Tag $PRERELEASE_TAG -> $SHA"
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
- name: ECR login via OIDC
id: ecr_login
uses: stellar/actions/sdf-ecr-login@main
- name: Verify production ECR tag does not exist
env:
RELEASE_VERSION: ${{ inputs.release_version }}
run: |
# Distinguish "tag absent" (ImageNotFoundException → proceed) from
# any other failure (auth/region/throttling/repo-missing → fail fast)
# so a misconfigured precheck cannot silently green-light a re-tag.
OUTPUT=$(aws ecr describe-images \
--repository-name prd/freighter-backend-v2 \
--image-ids imageTag="$RELEASE_VERSION" \
--region us-east-1 2>&1) && EXIT=0 || EXIT=$?
if [[ $EXIT -eq 0 ]]; then
echo "::error::ECR tag prd/freighter-backend-v2:$RELEASE_VERSION already exists."
exit 1
fi
if grep -q 'ImageNotFoundException' <<<"$OUTPUT"; then
echo "ECR tag $RELEASE_VERSION not present. Proceeding."
else
echo "::error::Unexpected error from aws ecr describe-images (exit $EXIT): $OUTPUT"
exit 1
fi
- name: Re-tag image from staging to production ECR
env:
ECR_REGISTRY: ${{ steps.ecr_login.outputs.ecr-registry }}
PRERELEASE_TAG: ${{ inputs.prerelease_tag }}
RELEASE_VERSION: ${{ inputs.release_version }}
run: |
STG_TAG="${ECR_REGISTRY}/stg/freighter-backend-v2:${PRERELEASE_TAG}"
PRD_TAG="${ECR_REGISTRY}/prd/freighter-backend-v2:${RELEASE_VERSION}"
echo "Re-tagging $STG_TAG -> $PRD_TAG"
docker buildx imagetools create --prefer-index=false --tag "$PRD_TAG" "$STG_TAG"
echo "Verifying digests match..."
STG_DIGEST=$(docker buildx imagetools inspect "$STG_TAG" --format '{{.Manifest.Digest}}')
PRD_DIGEST=$(docker buildx imagetools inspect "$PRD_TAG" --format '{{.Manifest.Digest}}')
echo "STG digest: $STG_DIGEST"
echo "PRD digest: $PRD_DIGEST"
if [[ "$STG_DIGEST" != "$PRD_DIGEST" ]]; then
echo "::error::Digest mismatch after re-tag: '$STG_DIGEST' vs '$PRD_DIGEST'."
exit 1
fi
echo "Promotion successful — bytes preserved."
- name: Create GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_VERSION: ${{ inputs.release_version }}
COMMIT_SHA: ${{ steps.resolve_sha.outputs.sha }}
run: |
gh release create "$RELEASE_VERSION" \
--target "$COMMIT_SHA" \
--title "$RELEASE_VERSION" \
--generate-notes