99permissions :
1010 contents : read
1111
12+ concurrency :
13+ group : release-${{ github.ref }}
14+ cancel-in-progress : false
15+
1216jobs :
1317 release :
1418 runs-on : ubuntu-latest
@@ -20,21 +24,21 @@ jobs:
2024 steps :
2125 - name : Generate GitHub App token
2226 id : generate-token
23- uses : actions/create-github-app-token@v1
27+ uses : actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf
2428 with :
2529 app-id : ${{ secrets.GH_APP_ID }}
2630 private-key : ${{ secrets.GH_APP_PRIVATE_KEY }}
2731
28- - uses : googleapis/release-please-action@v4
32+ - uses : googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38
2933 id : release
3034 with :
3135 token : ${{ steps.generate-token.outputs.token }}
3236
33- - uses : actions/checkout@v4
37+ - uses : actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3438 with :
3539 fetch-depth : 0
3640
37- - uses : actions/setup-node@v4
41+ - uses : actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
3842 with :
3943 node-version : 22
4044 registry-url : " https://registry.npmjs.org"
4347
4448 - name : Determine version
4549 id : version
50+ env :
51+ RELEASE_CREATED : ${{ steps.release.outputs.release_created }}
52+ RELEASE_VERSION : ${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}
53+ PR_HEAD_BRANCH : ${{ steps.release.outputs.pr && fromJSON(steps.release.outputs.pr).headBranchName }}
4654 run : |
47- if [ "${{ steps.release.outputs.release_created }}" == "true" ]; then
48- VERSION="${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}"
55+ set -euo pipefail
56+
57+ if [ "$RELEASE_CREATED" == "true" ]; then
58+ VERSION="$RELEASE_VERSION"
4959 TAG="latest"
5060
5161 # For release branches, check if this is the latest release branch
@@ -57,20 +67,35 @@ jobs:
5767 fi
5868 fi
5969 else
60- # RC only for main branch
70+ # RC only on main
6171 if [[ "$GITHUB_REF" != refs/heads/main ]]; then
6272 echo "skip=true" >> $GITHUB_OUTPUT
6373 exit 0
6474 fi
6575
66- # RC version from git describe, bump minor
67- DESCRIBE=$(git describe --tags --always --match 'v*' --exclude '*-rc*')
68- BASE=$(echo "$DESCRIBE" | sed 's/^v//' | cut -d'-' -f1)
69- MAJOR=$(echo "$BASE" | cut -d'.' -f1)
70- MINOR=$(echo "$BASE" | cut -d'.' -f2)
71- COMMITS=$(echo "$DESCRIBE" | cut -d'-' -f2)
72- NEXT_MINOR=$((MINOR + 1))
73- VERSION="${MAJOR}.${NEXT_MINOR}.0-rc.${COMMITS}"
76+ if [ -z "$PR_HEAD_BRANCH" ]; then
77+ # No pending release PR — skip to avoid version conflicts
78+ echo "skip=true" >> $GITHUB_OUTPUT
79+ exit 0
80+ fi
81+
82+ # Validate branch name to prevent git ref injection
83+ if [[ ! "$PR_HEAD_BRANCH" =~ ^[A-Za-z0-9._/-]+$ ]] || \
84+ [[ "$PR_HEAD_BRANCH" =~ \.\.|//|@\{|^-|/$ ]]; then
85+ echo "Invalid PR_HEAD_BRANCH: $PR_HEAD_BRANCH"
86+ exit 1
87+ fi
88+
89+ git fetch origin "refs/heads/$PR_HEAD_BRANCH"
90+ NEXT_VERSION=$(git show "FETCH_HEAD:package.json" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).version")
91+
92+ # Validate strict semver before use
93+ if [[ ! "$NEXT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
94+ echo "Invalid version in PR branch package.json: $NEXT_VERSION"
95+ exit 1
96+ fi
97+
98+ VERSION="${NEXT_VERSION}-rc.${{ github.run_number }}"
7499 TAG="rc"
75100 fi
76101 echo "version=$VERSION" >> $GITHUB_OUTPUT
@@ -79,20 +104,38 @@ jobs:
79104 - name : Build
80105 if : ${{ steps.version.outputs.skip != 'true' }}
81106 run : |
107+ set -euo pipefail
82108 echo "export const VERSION = '${{ steps.version.outputs.version }}';" > src/version.ts
83109 npm ci
84110 npm run build
85- npm version ${{ steps.version.outputs.version }} --no-git-tag-version
111+ npm version " ${{ steps.version.outputs.version }}" --no-git-tag-version --allow-same -version
86112
87113 - name : Publish
88114 if : ${{ steps.version.outputs.skip != 'true' }}
89- run : npm publish --provenance --tag ${{ steps.version.outputs.tag }}
115+ run : |
116+ set -euo pipefail
117+ NPM_VIEW_STDERR=$(mktemp)
118+ EXISTING=$(npm view "@supabase/ssr@${{ steps.version.outputs.version }}" version 2>"$NPM_VIEW_STDERR") || STATUS=$?
119+ if [ -n "$EXISTING" ]; then
120+ echo "Version ${{ steps.version.outputs.version }} already published on npm, skipping."
121+ rm -f "$NPM_VIEW_STDERR"
122+ exit 0
123+ elif [ "${STATUS:-0}" -ne 0 ] && ! grep -qiE 'E404|not found' "$NPM_VIEW_STDERR"; then
124+ echo "npm view failed unexpectedly:"
125+ cat "$NPM_VIEW_STDERR"
126+ rm -f "$NPM_VIEW_STDERR"
127+ exit 1
128+ fi
129+ rm -f "$NPM_VIEW_STDERR"
130+
131+ npm publish --provenance --tag "${{ steps.version.outputs.tag }}"
90132
91133 - name : Create GitHub pre-release
92134 if : ${{ steps.version.outputs.tag == 'rc' }}
93135 env :
94136 GH_TOKEN : ${{ steps.generate-token.outputs.token }}
95137 run : |
138+ set -euo pipefail
96139 gh release create "v${{ steps.version.outputs.version }}" \
97140 --title "v${{ steps.version.outputs.version }}" \
98141 --generate-notes \
0 commit comments