@@ -38,6 +38,7 @@ describe("install script", () => {
3838 SENTRY_CLI_NO_TELEMETRY : "1" ,
3939 SENTRY_TEST_DIR : testDir ,
4040 SENTRY_TEST_INSTALL_SCRIPT : installScript ,
41+ SENTRY_TEST_GITHUB_FAIL : "22" ,
4142 TMPDIR : testDir ,
4243 } ;
4344
@@ -46,6 +47,30 @@ describe("install script", () => {
4647 writeFileSync (
4748 join ( binDir , "curl" ) ,
4849 `#!/usr/bin/env bash
50+ for arg in "$@"; do
51+ case "$arg" in
52+ https://*) url="$arg" ;;
53+ esac
54+ done
55+ printf '%s\\n' "$url" >> "$SENTRY_TEST_DIR/download-urls"
56+ case "$url" in
57+ https://api.github.com/*)
58+ if [[ "\${SENTRY_TEST_GITHUB_FAIL:-0}" != "0" ]]; then
59+ echo "GitHub request failed (curl exit $SENTRY_TEST_GITHUB_FAIL)" >&2
60+ exit "$SENTRY_TEST_GITHUB_FAIL"
61+ fi
62+ printf '%s\\n' "$SENTRY_TEST_GITHUB_RESPONSE"
63+ exit 0
64+ ;;
65+ https://release-registry.services.sentry.io/apps/sentry/latest)
66+ if [[ "\${SENTRY_TEST_REGISTRY_FAIL:-0}" != "0" ]]; then
67+ echo "Registry request failed (curl exit $SENTRY_TEST_REGISTRY_FAIL)" >&2
68+ exit "$SENTRY_TEST_REGISTRY_FAIL"
69+ fi
70+ printf '%s\\n' "$SENTRY_TEST_REGISTRY_RESPONSE"
71+ exit 0
72+ ;;
73+ esac
4974cat <<'SCRIPT'
5075#!/usr/bin/env bash
5176set -euo pipefail
@@ -88,6 +113,125 @@ SCRIPT
88113 rmSync ( testDir , { recursive : true , force : true } ) ;
89114 } ) ;
90115
116+ test . each ( [
117+ '{"canonical":"app:sentry","version":"0.45.0"}' ,
118+ '{\n "canonical": "app:sentry",\n "version": "0.45.0"\n}' ,
119+ JSON . stringify (
120+ { version : "0.45.0" , description : "x" . repeat ( 96 * 1024 ) } ,
121+ null ,
122+ 2
123+ ) ,
124+ ] ) ( "installs the latest stable release when GitHub API access is blocked" , ( metadata ) => {
125+ env . SENTRY_TEST_REGISTRY_RESPONSE = metadata ;
126+ const result = spawnSync ( "bash" , [ installScript ] , {
127+ env,
128+ encoding : "utf8" ,
129+ timeout : 10_000 ,
130+ } ) ;
131+
132+ expect ( result . status , result . stdout + result . stderr ) . toBe ( 0 ) ;
133+ expect ( recorded ( "download-urls" ) ) . toEqual ( [
134+ "https://release-registry.services.sentry.io/apps/sentry/latest" ,
135+ expect . stringMatching (
136+ / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ g e t s e n t r y \/ c l i \/ r e l e a s e s \/ d o w n l o a d \/ 0 \. 4 5 \. 0 \/ s e n t r y - .+ \. g z $ /
137+ ) ,
138+ ] ) ;
139+ expect ( existsSync ( join ( installDir , "sentry" ) ) ) . toBe ( true ) ;
140+ } ) ;
141+
142+ test . each ( [
143+ { name : "HTTP error" , metadata : "" , failure : "22" } ,
144+ { name : "timeout" , metadata : "" , failure : "28" } ,
145+ { name : "missing version" , metadata : "{}" } ,
146+ { name : "non-JSON response" , metadata : "<html>Unavailable</html>" } ,
147+ { name : "nonstable version" , metadata : '{"version":"nightly"}' } ,
148+ ] ) ( "falls back to GitHub after a registry $name" , ( { metadata, failure } ) => {
149+ env . SENTRY_TEST_REGISTRY_RESPONSE = metadata ;
150+ env . SENTRY_TEST_REGISTRY_FAIL = failure ;
151+ env . SENTRY_TEST_GITHUB_FAIL = "0" ;
152+ env . SENTRY_TEST_GITHUB_RESPONSE = '{"tag_name":"0.45.0"}' ;
153+ const result = spawnSync ( "bash" , [ installScript ] , {
154+ env,
155+ encoding : "utf8" ,
156+ timeout : 10_000 ,
157+ } ) ;
158+
159+ expect ( result . status , result . stdout + result . stderr ) . toBe ( 0 ) ;
160+ expect ( result . stderr ) . toContain ( "Trying GitHub" ) ;
161+ expect ( recorded ( "download-urls" ) ) . toEqual ( [
162+ "https://release-registry.services.sentry.io/apps/sentry/latest" ,
163+ "https://api.github.com/repos/getsentry/cli/releases/latest" ,
164+ expect . stringMatching (
165+ / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ g e t s e n t r y \/ c l i \/ r e l e a s e s \/ d o w n l o a d \/ 0 \. 4 5 \. 0 \/ s e n t r y - .+ \. g z $ /
166+ ) ,
167+ ] ) ;
168+ expect ( existsSync ( join ( installDir , "sentry" ) ) ) . toBe ( true ) ;
169+ } ) ;
170+
171+ test . each ( [
172+ { name : "a leading v" , metadata : '{\n "tag_name": "v0.45.0"\n}' } ,
173+ {
174+ name : "large release metadata" ,
175+ metadata : JSON . stringify (
176+ { tag_name : "0.45.0" , body : "x" . repeat ( 96 * 1024 ) } ,
177+ null ,
178+ 2
179+ ) ,
180+ } ,
181+ ] ) ( "accepts a GitHub release with $name" , ( { metadata } ) => {
182+ env . SENTRY_TEST_REGISTRY_FAIL = "22" ;
183+ env . SENTRY_TEST_GITHUB_FAIL = "0" ;
184+ env . SENTRY_TEST_GITHUB_RESPONSE = metadata ;
185+ const result = spawnSync ( "bash" , [ installScript ] , {
186+ env,
187+ encoding : "utf8" ,
188+ timeout : 10_000 ,
189+ } ) ;
190+
191+ expect ( result . status , result . stdout + result . stderr ) . toBe ( 0 ) ;
192+ expect ( recorded ( "download-urls" ) . at ( - 1 ) ) . toMatch (
193+ / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ g e t s e n t r y \/ c l i \/ r e l e a s e s \/ d o w n l o a d \/ 0 \. 4 5 \. 0 \/ s e n t r y - .+ \. g z $ /
194+ ) ;
195+ expect ( existsSync ( join ( installDir , "sentry" ) ) ) . toBe ( true ) ;
196+ } ) ;
197+
198+ test . each ( [
199+ { name : "HTTP error" , metadata : "" , failure : "22" } ,
200+ { name : "timeout" , metadata : "" , failure : "28" } ,
201+ { name : "missing tag" , metadata : "{}" , failure : "0" } ,
202+ {
203+ name : "non-JSON response" ,
204+ metadata : "<html>Unavailable</html>" ,
205+ failure : "0" ,
206+ } ,
207+ { name : "nonstable tag" , metadata : '{"tag_name":"nightly"}' , failure : "0" } ,
208+ ] ) ( "stops when the registry and GitHub fail: $name" , ( {
209+ metadata,
210+ failure,
211+ } ) => {
212+ env . SENTRY_TEST_REGISTRY_FAIL = "22" ;
213+ env . SENTRY_TEST_GITHUB_RESPONSE = metadata ;
214+ env . SENTRY_TEST_GITHUB_FAIL = failure ;
215+ const result = spawnSync ( "bash" , [ installScript ] , {
216+ env,
217+ encoding : "utf8" ,
218+ timeout : 10_000 ,
219+ } ) ;
220+
221+ expect ( result . status ) . toBe ( 1 ) ;
222+ expect ( result . stderr ) . toContain (
223+ "Failed to fetch latest stable version from Sentry's release registry and GitHub"
224+ ) ;
225+ expect ( result . stderr ) . toContain ( "--version <version>" ) ;
226+ expect ( result . stderr ) . not . toContain ( "Unexpected failure at line" ) ;
227+ expect ( recorded ( "download-urls" ) ) . toEqual ( [
228+ "https://release-registry.services.sentry.io/apps/sentry/latest" ,
229+ "https://api.github.com/repos/getsentry/cli/releases/latest" ,
230+ ] ) ;
231+ expect ( recorded ( "setup-args" ) ) . toEqual ( [ ] ) ;
232+ expect ( existsSync ( join ( installDir , "sentry" ) ) ) . toBe ( false ) ;
233+ } ) ;
234+
91235 function recorded ( name : string ) : string [ ] {
92236 const path = join ( testDir , name ) ;
93237 return existsSync ( path )
@@ -169,6 +313,11 @@ process.exitCode = result.status ?? 1;
169313 ] ) ;
170314 expect ( recorded ( "post-args" ) ) . toEqual ( [ ] ) ;
171315 expect ( existsSync ( join ( installDir , "sentry" ) ) ) . toBe ( true ) ;
316+ expect ( recorded ( "download-urls" ) ) . toEqual ( [
317+ expect . stringMatching (
318+ / ^ h t t p s : \/ \/ g i t h u b \. c o m \/ g e t s e n t r y \/ c l i \/ r e l e a s e s \/ d o w n l o a d \/ 0 \. 3 1 \. 0 \/ s e n t r y - .+ \. g z $ /
319+ ) ,
320+ ] ) ;
172321 } ) ;
173322
174323 test ( "connects setup to the controlling terminal without launching another process" , ( ) => {
0 commit comments