Redirect from alias to canonical URL [azuredevops vso] (#2939)

As described in #2340, this provides a way to replace an old alias with a redirect. This makes it easier to migrate our URLs over time without making our matching patterns more complicated.

The 301 redirect is sent back to the requester. If a user pastes the aliased URL into the address bar, it'll be replaced in the browser with the new URL, which gently encourages them to migrate.

Close #2340
This commit is contained in:
Paul Melnikow
2019-02-08 01:07:50 -05:00
committed by GitHub
parent 4d45fe3ea0
commit 1486fd2fca
9 changed files with 271 additions and 34 deletions

View File

@@ -34,9 +34,8 @@ module.exports = class AzureDevOpsBuild extends BaseSvgScrapingService {
static get route() {
return {
base: '',
format: '(?:azure-devops|vso)/build/([^/]+)/([^/]+)/([^/]+)(?:/(.+))?',
capture: ['organization', 'projectId', 'definitionId', 'branch'],
base: 'azure-devops/build',
pattern: ':organization/:projectId/:definitionId/:branch*',
}
}
@@ -44,7 +43,7 @@ module.exports = class AzureDevOpsBuild extends BaseSvgScrapingService {
return [
{
title: 'Azure DevOps builds',
pattern: 'azure-devops/build/:organization/:projectId/:definitionId',
pattern: ':organization/:projectId/:definitionId',
namedParams: {
organization: 'totodem',
projectId: '8cf3ec0e-d0c2-4fcd-8206-ad204f254a96',
@@ -56,8 +55,7 @@ module.exports = class AzureDevOpsBuild extends BaseSvgScrapingService {
},
{
title: 'Azure DevOps builds (branch)',
pattern:
'azure-devops/build/:organization/:projectId/:definitionId/:branch',
pattern: ':organization/:projectId/:definitionId/:branch',
namedParams: {
organization: 'totodem',
projectId: '8cf3ec0e-d0c2-4fcd-8206-ad204f254a96',

View File

@@ -9,9 +9,7 @@ const { isBuildStatus } = require('../../lib/build-status')
const t = (module.exports = require('../tester').createServiceTester())
t.create('default branch')
.get(
'/azure-devops/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2.json'
)
.get('/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2.json')
.expectJSONTypes(
Joi.object().keys({
name: 'build',
@@ -20,9 +18,7 @@ t.create('default branch')
)
t.create('named branch')
.get(
'/azure-devops/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2/master.json'
)
.get('/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2/master.json')
.expectJSONTypes(
Joi.object().keys({
name: 'build',
@@ -31,22 +27,20 @@ t.create('named branch')
)
t.create('unknown definition')
.get(
'/azure-devops/build/larsbrinkhoff/953a34b9-5966-4923-a48a-c41874cfb5f5/515.json'
)
.get('/larsbrinkhoff/953a34b9-5966-4923-a48a-c41874cfb5f5/515.json')
.expectJSON({ name: 'build', value: 'definition not found' })
t.create('unknown project')
.get('/azure-devops/build/larsbrinkhoff/foo/515.json')
.get('/larsbrinkhoff/foo/515.json')
.expectJSON({ name: 'build', value: 'user or project not found' })
t.create('unknown user')
.get('/azure-devops/build/notarealuser/foo/515.json')
.get('/notarealuser/foo/515.json')
.expectJSON({ name: 'build', value: 'user or project not found' })
// The following build definition has always a partially succeeded status
t.create('partially succeeded build')
.get(
'/azure-devops/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/4.json?style=_shields_test'
'/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/4.json?style=_shields_test'
)
.expectJSON({ name: 'build', value: 'passing', color: 'orange' })

View File

@@ -29,9 +29,8 @@ module.exports = class AzureDevOpsRelease extends BaseSvgScrapingService {
static get route() {
return {
base: '',
format: '(?:azure-devops|vso)/release/([^/]+)/([^/]+)/([^/]+)/([^/]+)',
capture: ['organization', 'projectId', 'definitionId', 'environmentId'],
base: 'azure-devops/release',
pattern: ':organization/:projectId/:definitionId/:environmentId',
}
}
@@ -39,8 +38,6 @@ module.exports = class AzureDevOpsRelease extends BaseSvgScrapingService {
return [
{
title: 'Azure DevOps releases',
pattern:
'azure-devops/release/:organization/:projectId/:definitionId/:environmentId',
namedParams: {
organization: 'totodem',
projectId: '8cf3ec0e-d0c2-4fcd-8206-ad204f254a96',

View File

@@ -9,9 +9,7 @@ const { isBuildStatus } = require('../../lib/build-status')
const t = (module.exports = require('../tester').createServiceTester())
t.create('release status is succeeded')
.get(
'/azure-devops/release/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.json'
)
.get('/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.json')
.expectJSONTypes(
Joi.object().keys({
name: 'deployment',
@@ -20,24 +18,20 @@ t.create('release status is succeeded')
)
t.create('unknown environment')
.get(
'/azure-devops/release/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/515.json'
)
.get('/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/515.json')
.expectJSON({ name: 'deployment', value: 'user or environment not found' })
t.create('unknown definition')
.get(
'/azure-devops/release/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/515/515.json'
)
.get('/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/515/515.json')
.expectJSON({
name: 'deployment',
value: 'inaccessible or definition not found',
})
t.create('unknown project')
.get('/azure-devops/release/totodem/515/515/515.json')
.get('/totodem/515/515/515.json')
.expectJSON({ name: 'deployment', value: 'project not found' })
t.create('unknown user')
.get('/azure-devops/release/this-repo/does-not-exist/1/2.json')
.get('/this-repo/does-not-exist/1/2.json')
.expectJSON({ name: 'deployment', value: 'user or environment not found' })

View File

@@ -0,0 +1,31 @@
'use strict'
const { redirector } = require('..')
module.exports = [
redirector({
category: 'build',
route: {
base: 'vso/build',
pattern: ':organization/:projectId/:definitionId/:branch*',
},
target: ({ organization, projectId, definitionId, branch }) => {
let path = `/azure-devops/build/${organization}/${projectId}/${definitionId}`
if (branch) {
path += `/${branch}`
}
return path
},
dateAdded: new Date('2019-02-08'),
}),
redirector({
category: 'build',
route: {
base: 'vso/release',
pattern: ':organization/:projectId/:definitionId/:environmentId',
},
target: ({ organization, projectId, definitionId, environmentId }) =>
`/azure-devops/release/${organization}/${projectId}/${definitionId}/${environmentId}`,
dateAdded: new Date('2019-02-08'),
}),
]

View File

@@ -0,0 +1,38 @@
'use strict'
const { ServiceTester } = require('../tester')
const t = (module.exports = new ServiceTester({
id: 'vso',
title: 'VSO',
}))
t.create('Build: default branch')
.get('/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2.svg', {
followRedirect: false,
})
.expectStatus(301)
.expectHeader(
'Location',
'/azure-devops/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2.svg'
)
t.create('Build: named branch')
.get('/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2/master.svg', {
followRedirect: false,
})
.expectStatus(301)
.expectHeader(
'Location',
'/azure-devops/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2/master.svg'
)
t.create('Release status')
.get('/release/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.svg', {
followRedirect: false,
})
.expectStatus(301)
.expectHeader(
'Location',
'/azure-devops/release/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/1/1.svg'
)