Skip to content

Commit e87d82f

Browse files
authored
Added custom bucket url support for [Scoop] (#9984)
* added support for custom bucket urls in Scoop Version shield * tolerate URLs with a trailing slash * added description with example to bucket query param
1 parent 0a059e0 commit e87d82f

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

services/scoop/scoop-version.service.js

+30-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { URL } from 'url'
12
import Joi from 'joi'
23
import { NotFound, pathParam, queryParam } from '../index.js'
34
import { ConditionalGithubAuthV3Service } from '../github/github-auth-service.js'
@@ -37,7 +38,12 @@ export default class ScoopVersion extends ConditionalGithubAuthV3Service {
3738
'[Scoop](https://scoop.sh/) is a command-line installer for Windows',
3839
parameters: [
3940
pathParam({ name: 'app', example: 'ngrok' }),
40-
queryParam({ name: 'bucket', example: 'extras' }),
41+
queryParam({
42+
name: 'bucket',
43+
description:
44+
"App's containing bucket. Can either be a name (e.g `extras`) or a URL to a GitHub Repo (e.g `https://github.com/jewlexx/personal-scoop`)",
45+
example: 'extras',
46+
}),
4147
],
4248
},
4349
},
@@ -60,9 +66,30 @@ export default class ScoopVersion extends ConditionalGithubAuthV3Service {
6066
})
6167
}
6268
const bucket = queryParams.bucket || 'main'
63-
const bucketUrl = this.buckets[bucket]
69+
let bucketUrl = this.buckets[bucket]
6470
if (!bucketUrl) {
65-
throw new NotFound({ prettyMessage: `bucket "${bucket}" not found` })
71+
// Parsing URL here will throw an error if the url is invalid
72+
try {
73+
const url = new URL(decodeURIComponent(bucket))
74+
75+
// Throw errors to go to jump to catch statement
76+
// The error messages here are purely for code readability, and will never reach the user.
77+
if (url.hostname !== 'github.com') {
78+
throw new Error('Not a GitHub URL')
79+
}
80+
const path = url.pathname.split('/').filter(value => value !== '')
81+
82+
if (path.length !== 2) {
83+
throw new Error('Not a valid GitHub Repo')
84+
}
85+
86+
const [user, repo] = path
87+
88+
// Reconstructing the url here ensures that the url will match the regex
89+
bucketUrl = `https://github.com/${user}/${repo}`
90+
} catch (e) {
91+
throw new NotFound({ prettyMessage: `bucket "${bucket}" not found` })
92+
}
6693
}
6794
const {
6895
groups: { user, repo },

services/scoop/scoop-version.tester.js

+51
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,54 @@ t.create('version (wrong bucket)')
4040
label: 'scoop',
4141
message: 'bucket "not-a-real-bucket" not found',
4242
})
43+
44+
// version (bucket url)
45+
const validBucketUrl = encodeURIComponent(
46+
'https://github.com/jewlexx/personal-scoop',
47+
)
48+
49+
t.create('version (valid bucket url)')
50+
.get(`/v/sfsu.json?bucket=${validBucketUrl}`)
51+
.expectBadge({
52+
label: 'scoop',
53+
message: isVPlusDottedVersionNClauses,
54+
})
55+
56+
const validBucketUrlTrailingSlash = encodeURIComponent(
57+
'https://github.com/jewlexx/personal-scoop/',
58+
)
59+
60+
t.create('version (valid bucket url)')
61+
.get(`/v/sfsu.json?bucket=${validBucketUrlTrailingSlash}`)
62+
.expectBadge({
63+
label: 'scoop',
64+
message: isVPlusDottedVersionNClauses,
65+
})
66+
67+
t.create('version (not found in custom bucket)')
68+
.get(`/v/not-a-real-app.json?bucket=${validBucketUrl}`)
69+
.expectBadge({
70+
label: 'scoop',
71+
message: `not-a-real-app not found in bucket "${decodeURIComponent(validBucketUrl)}"`,
72+
})
73+
74+
const nonGithubUrl = encodeURIComponent('https://example.com/')
75+
76+
t.create('version (non-github url)')
77+
.get(`/v/not-a-real-app.json?bucket=${nonGithubUrl}`)
78+
.expectBadge({
79+
label: 'scoop',
80+
message: `bucket "${decodeURIComponent(nonGithubUrl)}" not found`,
81+
})
82+
83+
const nonBucketRepo = encodeURIComponent('https://github.com/jewlexx/sfsu')
84+
85+
t.create('version (non-bucket repo)')
86+
.get(`/v/sfsu.json?bucket=${nonBucketRepo}`)
87+
.expectBadge({
88+
label: 'scoop',
89+
// !!! Important note here
90+
// It is hard to tell if a repo is actually a scoop bucket, without getting the contents
91+
// As such, a helpful error message here, which would require testing if the url is a valid scoop bucket, is difficult.
92+
message: `sfsu not found in bucket "${decodeURIComponent(nonBucketRepo)}"`,
93+
})

0 commit comments

Comments
 (0)