@@ -39,7 +39,18 @@ if (!validSpecifiers.includes(versionSpecifier) && !isValidVersion) {
39
39
process . exit ( 1 )
40
40
}
41
41
42
+ function safeExec ( cmd : string , opts = { } ) {
43
+ try {
44
+ return execSync ( cmd , { stdio : 'inherit' , ...opts } )
45
+ } catch ( err ) {
46
+ console . error ( `❌ Command failed: ${ cmd } ` )
47
+ throw err
48
+ }
49
+ }
50
+
42
51
; ( async ( ) => {
52
+ // --- VERSION AND BUILD ---
53
+
43
54
const { workspaceVersion, projectsVersionData } = await releaseVersion ( {
44
55
verbose : true ,
45
56
gitCommit : false ,
@@ -49,28 +60,37 @@ if (!validSpecifiers.includes(versionSpecifier) && !isValidVersion) {
49
60
50
61
// Update version.ts files with the new versions
51
62
console . log ( '\n📦 Updating version.ts files...' )
52
- execSync ( 'npx tsx scripts/update-version-files.ts' , { stdio : 'inherit' } )
63
+ safeExec ( 'npx tsx scripts/update-version-files.ts' )
53
64
54
65
// Rebuild packages with correct versions
55
66
console . log ( '\n🔨 Rebuilding packages with new versions...' )
56
- execSync ( 'npx nx run-many --target=build --all' , { stdio : 'inherit' } )
67
+ safeExec ( 'npx nx run-many --target=build --all' )
57
68
console . log ( '✅ Build complete\n' )
58
69
70
+ // --- GIT AUTH SETUP FOR TAGGING/CHANGELOG ---
71
+
59
72
// releaseChangelog should use the GitHub token with permission for tagging
60
73
// before switching the token, backup the GITHUB_TOKEN so that it
61
74
// can be restored afterwards and used by releasePublish. We can't use the same
62
75
// token, because releasePublish wants a token that has the id_token: write permission
63
76
// so that we can use OIDC for trusted publishing
77
+
64
78
const gh_token_bak = process . env . GITHUB_TOKEN
65
79
process . env . GITHUB_TOKEN = process . env . RELEASE_GITHUB_TOKEN
66
- // backup original auth header
67
- const originalAuth = execSync ( 'git config --local http.https://github.com/.extraheader' )
68
- . toString ( )
69
- . trim ( )
80
+
81
+ // backup original auth header if exists
82
+ let originalAuth = ''
83
+ try {
84
+ originalAuth = execSync ( 'git config --local http.https://github.com/.extraheader' )
85
+ . toString ( )
86
+ . trim ( )
87
+ } catch { }
88
+
70
89
// switch the token used
71
90
const authHeader = `AUTHORIZATION: basic ${ Buffer . from ( `x-access-token:${ process . env . RELEASE_GITHUB_TOKEN } ` ) . toString ( 'base64' ) } `
72
- execSync ( `git config --local http.https://github.com/.extraheader "${ authHeader } "` )
91
+ safeExec ( `git config --local http.https://github.com/.extraheader "${ authHeader } "` )
73
92
93
+ // ---- CHANGELOG GENERATION ---
74
94
const result = await releaseChangelog ( {
75
95
versionData : projectsVersionData ,
76
96
version : workspaceVersion ,
@@ -79,12 +99,18 @@ if (!validSpecifiers.includes(versionSpecifier) && !isValidVersion) {
79
99
stageChanges : false ,
80
100
} )
81
101
102
+ // --- RESTORE GIT AUTH FOR PUBLISHING ---
82
103
// npm publish with OIDC
83
104
// not strictly necessary to restore the header but do it incase we require it later
84
- execSync ( `git config --local http.https://github.com/.extraheader "${ originalAuth } "` )
85
- // restore the GH token
105
+ if ( originalAuth ) {
106
+ safeExec ( `git config --local http.https://github.com/.extraheader "${ originalAuth } "` )
107
+ } else {
108
+ safeExec ( `git config --local --unset http.https://github.com/.extraheader || true` )
109
+ }
86
110
process . env . GITHUB_TOKEN = gh_token_bak
87
111
112
+ // --- NPM PUBLISH ---
113
+
88
114
const publishResult = await releasePublish ( {
89
115
registry : 'https://registry.npmjs.org/' ,
90
116
access : 'public' ,
@@ -95,20 +121,36 @@ if (!validSpecifiers.includes(versionSpecifier) && !isValidVersion) {
95
121
// Publish gotrue-js as legacy mirror of auth-js
96
122
console . log ( '\n📦 Publishing @supabase/gotrue-js (legacy mirror)...' )
97
123
try {
98
- execSync ( 'npx tsx scripts/publish-gotrue-legacy.ts --tag=latest' , { stdio : 'inherit' } )
124
+ safeExec ( 'npx tsx scripts/publish-gotrue-legacy.ts --tag=latest' )
99
125
} catch ( error ) {
100
126
console . error ( '❌ Failed to publish gotrue-js legacy package:' , error )
101
127
// Don't fail the entire release if gotrue-js fails
102
128
console . log ( '⚠️ Continuing with release despite gotrue-js publish failure' )
103
129
}
104
130
105
- // ---- Create release branch + PR ----
106
- // switch back to the releaser GitHub token
131
+ // ---- CREATE RELEASE BRANCH + PR ----
107
132
process . env . GITHUB_TOKEN = process . env . RELEASE_GITHUB_TOKEN
133
+
134
+ // REMOVE ALL credential helpers and .extraheader IMMEDIATELY BEFORE PUSH
135
+ try {
136
+ safeExec ( 'git config --global --unset credential.helper || true' )
137
+ } catch { }
138
+ try {
139
+ safeExec ( 'git config --local --unset credential.helper || true' )
140
+ } catch { }
141
+ try {
142
+ safeExec ( 'git config --local --unset http.https://github.com/.extraheader || true' )
143
+ } catch { }
144
+
145
+ // Ensure remote is set again before push
146
+ if ( process . env . RELEASE_GITHUB_TOKEN ) {
147
+ const remoteUrl = `https://x-access-token:${ process . env . RELEASE_GITHUB_TOKEN } @github.com/supabase/supabase-js.git`
148
+ safeExec ( `git remote set-url origin "${ remoteUrl } "` )
149
+ }
150
+
108
151
const version = result . workspaceChangelog ?. releaseVersion . rawVersion || workspaceVersion
109
152
110
153
// Validate version to prevent command injection
111
- // Version should match semver pattern or be a valid npm version specifier
112
154
if (
113
155
! version ||
114
156
! / ^ ( v ? \d + \. \d + \. \d + ( - [ a - z A - Z 0 - 9 . - ] + ) ? | p a t c h | m i n o r | m a j o r | p r e p a t c h | p r e m i n o r | p r e m a j o r | p r e r e l e a s e ) $ / . test (
@@ -122,29 +164,31 @@ if (!validSpecifiers.includes(versionSpecifier) && !isValidVersion) {
122
164
const branchName = `release-${ version } `
123
165
124
166
try {
125
- execSync ( `git checkout -b ${ branchName } ` )
126
- execSync ( 'git add CHANGELOG.md || true' )
127
- execSync ( 'git add packages/**/CHANGELOG.md || true' )
167
+ safeExec ( `git checkout -b ${ branchName } ` )
168
+ safeExec ( 'git add CHANGELOG.md || true' )
169
+ safeExec ( 'git add packages/**/CHANGELOG.md || true' )
128
170
129
171
// Commit changes if any
130
172
try {
131
- execSync ( `git commit -m "chore(release): publish version ${ version } "` )
173
+ safeExec ( `git commit -m "chore(release): publish version ${ version } "` )
132
174
} catch {
133
175
console . log ( 'No changes to commit' )
134
176
}
135
177
136
- execSync ( `git push origin ${ branchName } ` )
178
+ // DEBUG: Show credential config and remote before push
179
+ safeExec ( 'git config --local --get http.https://github.com/.extraheader || true' )
180
+
181
+ safeExec ( `git push origin ${ branchName } ` )
137
182
138
183
// Open PR using GitHub CLI
139
- execSync (
140
- `gh pr create --base master --head ${ branchName } --title "chore(release): ${ version } " --body "Automated release PR for ${ version } "` ,
141
- { stdio : 'inherit' }
184
+ safeExec (
185
+ `gh pr create --base master --head ${ branchName } --title "chore(release): version ${ version } changelogs" --body "Automated PR to update changelogs for version ${ version } ."`
142
186
)
143
187
144
188
// Enable auto-merge
145
- execSync ( `gh pr merge --auto --squash` , { stdio : 'inherit' } )
189
+ safeExec ( `gh pr merge --auto --squash` )
146
190
147
- execSync ( 'git stash' )
191
+ safeExec ( 'git stash' )
148
192
console . log ( '✅ Stashed package.json changes' )
149
193
} catch ( err ) {
150
194
console . error ( '❌ Failed to push release branch or open PR' , err )
0 commit comments