11name : Release Production
22
33on :
4- push :
5- tags :
6- - " v*"
7- - " !v*-dev*" # Exclude all dev tags
4+ workflow_dispatch :
5+ inputs :
6+ dev_tag :
7+ description : ' Dev tag to promote (e.g. v1.0.0-dev)'
8+ required : true
9+ type : string
810
911permissions :
1012 contents : write
1416 NODE_VERSION : " 20.x"
1517
1618jobs :
17- approval :
19+ build-and-publish :
1820 runs-on : ubuntu-latest
19- environment : production
2021 steps :
21- - name : Production release approved
22+ - name : Validate tag
2223 run : |
23- echo "Production release ${{ github.ref_name }} approved by CODEOWNER"
24- echo "Proceeding with build and publish..."
24+ DEV_TAG="${{ inputs.dev_tag }}"
25+
26+ if [[ ! "$DEV_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-dev ]]; then
27+ echo "Invalid dev tag: $DEV_TAG"
28+ echo "Expected: v1.0.0-dev or v1.0.0-dev.1"
29+ exit 1
30+ fi
31+
32+ PROD_TAG="${DEV_TAG%%-dev*}"
33+ PACKAGE_VERSION="${PROD_TAG#v}"
34+
35+ echo "DEV_TAG=$DEV_TAG" >> $GITHUB_ENV
36+ echo "PROD_TAG=$PROD_TAG" >> $GITHUB_ENV
37+ echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV
2538
26- build-and-publish :
27- needs : approval
28- runs-on : ubuntu-latest
29- steps :
3039 - name : Checkout
3140 uses : actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3241 with :
42+ ref : ${{ inputs.dev_tag }}
3343 fetch-depth : 0
3444
35- - name : Set version from tag
45+ - name : Verify dev tag
3646 run : |
37- VERSION="${{ github.ref_name }}"
38- # Clean leading v from provided version
39- PACKAGE_VERSION="${VERSION#v}"
40- # Extract base semantic version (x.y.z) - strip everything after first hyphen
41- BASE_VERSION="${VERSION%%-*}"
42- echo "VERSION=$VERSION" >> $GITHUB_ENV
43- echo "PACKAGE_VERSION=$PACKAGE_VERSION" >> $GITHUB_ENV
44- echo "BASE_VERSION=$BASE_VERSION" >> $GITHUB_ENV
45- echo "Building production version: $PACKAGE_VERSION"
46- echo "Will verify dev tag exists for base version: $BASE_VERSION"
47-
48- - name : Verify dev testing occurred
49- run : |
50- echo "Looking for dev tag with base version: ${{ env.BASE_VERSION }}"
51-
52- # Check if any dev tag exists for this semantic version (e.g., v0.1.0-dev*)
53- DEV_TAGS=$(git tag -l "${{ env.BASE_VERSION }}-dev*" | head -10)
54- if [ -z "$DEV_TAGS" ]; then
55- echo "ERROR: No dev tag found for version ${{ env.BASE_VERSION }}"
56- echo ""
57- echo "Available dev tags:"
58- git tag -l "*-dev*" | head -10 || echo "No dev tags found"
59- echo ""
60- echo "Must test in dev first: git tag ${{ env.BASE_VERSION }}-dev"
47+ if ! git rev-parse "${{ env.DEV_TAG }}" >/dev/null 2>&1; then
48+ echo "Dev tag not found: ${{ env.DEV_TAG }}"
49+ echo "Recent dev tags:"
50+ git tag -l "*-dev*" | tail -5
6151 exit 1
6252 fi
6353
64- echo "✅ Found dev tags for ${{ env.BASE_VERSION }}:"
65- echo "$DEV_TAGS"
66-
67- # Verify dev and prod tags point to same commit
68- PROD_COMMIT=$(git rev-list -n 1 "${{ github.ref_name }}")
69- echo "Production tag ${{ github.ref_name }} points to commit: $PROD_COMMIT"
70-
71- for DEV_TAG in $DEV_TAGS; do
72- DEV_COMMIT=$(git rev-list -n 1 "$DEV_TAG")
73- echo "Dev tag $DEV_TAG points to commit: $DEV_COMMIT"
74-
75- if [ "$DEV_COMMIT" = "$PROD_COMMIT" ]; then
76- echo "✅ Dev tag $DEV_TAG verified - same commit as production tag "
77- echo "VERIFIED_DEV_TAG=$DEV_TAG" >> $GITHUB_ENV
78- exit 0
54+ DEV_COMMIT=$(git rev-list -n 1 " ${{ env.DEV_TAG }}")
55+ echo "DEV_COMMIT=$DEV_COMMIT" >> $GITHUB_ENV
56+
57+ - name : Check existing prod tag
58+ run : |
59+ if git rev-parse " ${{ env.PROD_TAG }}" >/dev/null 2>&1; then
60+ EXISTING=$(git rev-list -n 1 "${{ env.PROD_TAG }}")
61+ if [ "$EXISTING" = "${{ env.DEV_COMMIT }}" ]; then
62+ echo "Prod tag already exists on same commit, skipping creation"
63+ echo "PROD_TAG_EXISTS=true" >> $GITHUB_ENV
64+ else
65+ echo "Prod tag exists on different commit - can't proceed"
66+ echo " Existing: $EXISTING "
67+ echo " Dev tag: ${{ env.DEV_COMMIT }}"
68+ exit 1
7969 fi
80- done
81-
82- echo "ERROR: No dev tag points to the same commit as production tag ${{ github.ref_name }}"
83- echo "Production commit: $PROD_COMMIT"
84- echo "Dev tags and their commits:"
85- for DEV_TAG in $DEV_TAGS; do
86- DEV_COMMIT=$(git rev-list -n 1 "$DEV_TAG")
87- echo " $DEV_TAG: $DEV_COMMIT"
88- done
89- echo ""
90- echo "Create a dev tag on the same commit: git tag ${{ env.BASE_VERSION }}-dev $PROD_COMMIT"
91- exit 1
70+ else
71+ echo "PROD_TAG_EXISTS=false" >> $GITHUB_ENV
72+ fi
73+
74+ - name : Create prod tag
75+ if : env.PROD_TAG_EXISTS == 'false'
76+ run : |
77+ git config user.name "github-actions[bot]"
78+ git config user.email "github-actions[bot]@users.noreply.github.com"
79+
80+ git tag -a "${{ env.PROD_TAG }}" "${{ env.DEV_COMMIT }}" \
81+ -m "Release ${{ env.PROD_TAG }}" \
82+ -m "Promoted from ${{ env.DEV_TAG }}"
83+
84+ git push origin "${{ env.PROD_TAG }}"
9285
9386 - name : Setup pnpm
9487 uses : pnpm/action-setup@v4
@@ -103,84 +96,52 @@ jobs:
10396 cache : " pnpm"
10497
10598 - name : Install dependencies
106- working-directory : .
10799 run : pnpm install --frozen-lockfile
108100
109- - name : Build SDK (prod) - dependency for CLI
101+ - name : Build SDK
110102 working-directory : ./packages/sdk
111103 env :
112104 BUILD_TYPE : prod
113105 PACKAGE_VERSION : ${{ env.PACKAGE_VERSION }}
114106 POSTHOG_API_KEY_BUILD_TIME : ${{ secrets.POSTHOG_API_KEY }}
115- run : |
116- pnpm run build
107+ run : pnpm run build
117108
118- - name : Build CLI (prod)
109+ - name : Build CLI
119110 working-directory : ./packages/cli
120111 env :
121112 BUILD_TYPE : prod
122113 PACKAGE_VERSION : ${{ env.PACKAGE_VERSION }}
123114 POSTHOG_API_KEY_BUILD_TIME : ${{ secrets.POSTHOG_API_KEY }}
124- run : |
125- pnpm run build
126-
127- - name : Get short sha
128- run : echo "SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
129- env :
130- GITHUB_SHA : ${{ github.sha }}
115+ run : pnpm run build
131116
132- - name : Generate SDK VERSION file
133- working-directory : ./packages/sdk
117+ - name : Generate VERSION files
134118 env :
135119 PACKAGE_VERSION : ${{ env.PACKAGE_VERSION }}
136- GITHUB_SHA : ${{ env.SHORT_SHA }}
120+ GITHUB_SHA : ${{ env.DEV_COMMIT }}
137121 run : |
138- node scripts/generate-version.js
122+ export GITHUB_SHA="${GITHUB_SHA::7}"
123+ (cd packages/sdk && node scripts/generate-version.js)
124+ (cd packages/cli && node scripts/generate-version.js)
139125
140- - name : Generate CLI VERSION file
141- working-directory : ./packages/cli
142- env :
143- PACKAGE_VERSION : ${{ env.PACKAGE_VERSION }}
144- GITHUB_SHA : ${{ env.SHORT_SHA }}
145- run : |
146- node scripts/generate-version.js
147-
148- - name : Update SDK package.json for publishing
149- working-directory : ./packages/sdk
150- run : |
151- # Update version (keep default package name)
152- npm pkg set version="${{ env.PACKAGE_VERSION }}"
153-
154- - name : Publish SDK to npm (prod)
126+ - name : Publish SDK
155127 working-directory : ./packages/sdk
156128 env :
157129 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
158130 run : |
159- npm publish --tag latest --access public
160-
161- - name : Update CLI package.json for publishing
162- working-directory : ./packages/cli
163- run : |
164- # Update version (keep default package name)
165131 npm pkg set version="${{ env.PACKAGE_VERSION }}"
166- # Update SDK dependency to match published version
167- npm pkg set "dependencies.@layr-labs/ecloud-sdk"="${{ env.PACKAGE_VERSION }}"
168- # Verify changes
169- cat package.json | grep -A 2 '"name"'
170- cat package.json | grep -A 1 '"@layr-labs/ecloud-sdk"'
132+ npm publish --tag latest --access public
171133
172- - name : Publish CLI to npm (prod)
134+ - name : Publish CLI
173135 working-directory : ./packages/cli
174136 env :
175137 NODE_AUTH_TOKEN : ${{ secrets.NPM_TOKEN }}
176138 run : |
139+ npm pkg set version="${{ env.PACKAGE_VERSION }}"
140+ npm pkg set "dependencies.@layr-labs/ecloud-sdk"="${{ env.PACKAGE_VERSION }}"
177141 npm publish --tag latest --access public
178142
179143 - name : Summary
180144 run : |
181- echo "🚀 Production release published successfully!"
182- echo "📦 SDK Package: @layr-labs/ecloud-sdk@${{ env.PACKAGE_VERSION }} (tag: latest)"
183- echo "📦 CLI Package: @layr-labs/ecloud-cli@${{ env.PACKAGE_VERSION }} (tag: latest)"
184- echo "🏷️ Tag: latest"
185- echo "🔒 Verified dev testing completed with matching commit from ${{ env.VERIFIED_DEV_TAG }}"
186- echo "🔗 Install with: npm install -g @layr-labs/ecloud-cli@latest"
145+ echo "Published @layr-labs/ecloud-sdk@${{ env.PACKAGE_VERSION }}"
146+ echo "Published @layr-labs/ecloud-cli@${{ env.PACKAGE_VERSION }}"
147+ echo "Tag: ${{ env.PROD_TAG }} (from ${{ env.DEV_TAG }})"
0 commit comments