Skip to content

Commit 0f13224

Browse files
committed
👷 refactor deployment scripts to remove hardcoded list of DCs and sites
1 parent 247005e commit 0f13224

File tree

9 files changed

+154
-66
lines changed

9 files changed

+154
-66
lines changed

‎.gitlab/deploy-auto.yml‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ stages:
1717
- VERSION=$(node -p -e "require('./lerna.json').version")
1818
- yarn
1919
- yarn build:bundle
20-
- node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $UPLOAD_PATH --check-monitors
20+
- node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $DATACENTER --check-monitors
2121

2222
step-1_deploy-prod-minor-dcs:
2323
when: manual
@@ -26,7 +26,7 @@ step-1_deploy-prod-minor-dcs:
2626
- .base-configuration
2727
- .deploy-prod
2828
variables:
29-
UPLOAD_PATH: minor-dcs
29+
DATACENTER: minor-dcs
3030

3131
step-2_deploy-prod-eu1:
3232
needs:
@@ -35,7 +35,7 @@ step-2_deploy-prod-eu1:
3535
- .base-configuration
3636
- .deploy-prod
3737
variables:
38-
UPLOAD_PATH: eu1
38+
DATACENTER: eu1
3939

4040
step-3_deploy-prod-us1:
4141
needs:
@@ -44,7 +44,7 @@ step-3_deploy-prod-us1:
4444
- .base-configuration
4545
- .deploy-prod
4646
variables:
47-
UPLOAD_PATH: us1
47+
DATACENTER: us1
4848

4949
step-4_deploy-prod-gov:
5050
needs:
@@ -53,7 +53,7 @@ step-4_deploy-prod-gov:
5353
- .base-configuration
5454
- .deploy-prod
5555
variables:
56-
UPLOAD_PATH: root
56+
DATACENTER: gov
5757

5858
step-5_publish-npm:
5959
needs:

‎.gitlab/deploy-manual.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,35 @@ stages:
1919
- VERSION=$(node -p -e "require('./lerna.json').version")
2020
- yarn
2121
- yarn build:bundle
22-
- node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $UPLOAD_PATH --no-check-monitors
22+
- node ./scripts/deploy/deploy-prod-dc.ts v${VERSION%%.*} $DATACENTER --no-check-monitors
2323

2424
step-1_deploy-prod-minor-dcs:
2525
extends:
2626
- .base-configuration
2727
- .deploy-prod
2828
variables:
29-
UPLOAD_PATH: minor-dcs
29+
DATACENTER: minor-dcs
3030

3131
step-2_deploy-prod-eu1:
3232
extends:
3333
- .base-configuration
3434
- .deploy-prod
3535
variables:
36-
UPLOAD_PATH: eu1
36+
DATACENTER: eu1
3737

3838
step-3_deploy-prod-us1:
3939
extends:
4040
- .base-configuration
4141
- .deploy-prod
4242
variables:
43-
UPLOAD_PATH: us1
43+
DATACENTER: us1
4444

4545
step-4_deploy-prod-gov:
4646
extends:
4747
- .base-configuration
4848
- .deploy-prod
4949
variables:
50-
UPLOAD_PATH: root
50+
DATACENTER: root
5151

5252
step-5_publish-npm:
5353
stage: deploy
@@ -80,7 +80,7 @@ step-7_create-github-release:
8080
- node scripts/release/create-github-release.ts
8181

8282
# This step is used to deploy the SDK to a new datacenter.
83-
# the `UPLOAD_PATH` variable needs to be provided as an argument when starting the manual job
83+
# the `DATACENTER` variable needs to be provided as an argument when starting the manual job
8484
optional_step-deploy-to-new-datacenter:
8585
extends:
8686
- .base-configuration

‎scripts/deploy/check-monitors.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
*/
66
import { printLog, runMain, fetchHandlingError } from '../lib/executionUtils.ts'
77
import { getTelemetryOrgApiKey, getTelemetryOrgApplicationKey } from '../lib/secrets.ts'
8-
import { siteByDatacenter } from '../lib/datacenter.ts'
8+
import { getSite } from '../lib/datacenter.ts'
99
import { browserSdkVersion } from '../lib/browserSdkVersion.ts'
1010

1111
const datacenters = process.argv[2].split(',')
1212

1313
runMain(async () => {
1414
for (const datacenter of datacenters) {
15-
const site = siteByDatacenter[datacenter]
15+
const site = getSite(datacenter)
1616
const apiKey = getTelemetryOrgApiKey(site)
1717
const applicationKey = getTelemetryOrgApplicationKey(site)
1818

‎scripts/deploy/deploy-prod-dc.spec.ts‎

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import assert from 'node:assert/strict'
22
import path from 'node:path'
3-
import { beforeEach, before, describe, it, mock } from 'node:test'
3+
import { beforeEach, before, describe, it, mock, afterEach } from 'node:test'
44
import type { CommandDetail } from './lib/testHelpers.ts'
5-
import { mockModule, mockCommandImplementation } from './lib/testHelpers.ts'
5+
import { mockCommandImplementation, mockModule } from './lib/testHelpers.ts'
66

7-
// eslint-disable-next-line
8-
describe.only('deploy-prod-dc', () => {
7+
describe('deploy-prod-dc', () => {
98
const commandMock = mock.fn()
10-
119
let commands: CommandDetail[]
1210

1311
before(async () => {
@@ -21,6 +19,10 @@ describe.only('deploy-prod-dc', () => {
2119
commands = mockCommandImplementation(commandMock)
2220
})
2321

22+
afterEach(() => {
23+
mock.restoreAll()
24+
})
25+
2426
it('should deploy a given datacenter', async () => {
2527
await runScript('./deploy-prod-dc.ts', 'v6', 'us1')
2628

@@ -42,22 +44,30 @@ describe.only('deploy-prod-dc', () => {
4244
])
4345
})
4446

45-
it('should only check monitors before deploying if the upload path is root', async () => {
46-
await runScript('./deploy-prod-dc.ts', 'v6', 'root', '--check-monitors')
47+
it('should deploy all minor datacenters', async () => {
48+
await runScript('./deploy-prod-dc.ts', 'v6', 'minor-dcs', '--no-check-monitors')
4749

4850
assert.deepEqual(commands, [
49-
{ command: 'node ./scripts/deploy/check-monitors.ts root' },
50-
{ command: 'node ./scripts/deploy/deploy.ts prod v6 root' },
51-
{ command: 'node ./scripts/deploy/upload-source-maps.ts v6 root' },
51+
{ command: 'node ./scripts/deploy/deploy.ts prod v6 ap1,ap2,us3,us5' },
52+
{ command: 'node ./scripts/deploy/upload-source-maps.ts v6 ap1,ap2,us3,us5' },
5253
])
5354
})
5455

55-
it('should deploy all minor datacenters', async () => {
56-
await runScript('./deploy-prod-dc.ts', 'v6', 'minor-dcs', '--no-check-monitors')
56+
it('should deploy all private regions', async () => {
57+
await runScript('./deploy-prod-dc.ts', 'v6', 'private-regions', '--no-check-monitors')
58+
59+
assert.deepEqual(commands, [
60+
{ command: 'node ./scripts/deploy/deploy.ts prod v6 prtest00,prtest01' },
61+
{ command: 'node ./scripts/deploy/upload-source-maps.ts v6 prtest00,prtest01' },
62+
])
63+
})
64+
65+
it('should deploy gov datacenters to the root upload path', async () => {
66+
await runScript('./deploy-prod-dc.ts', 'v6', 'gov', '--no-check-monitors')
5767

5868
assert.deepEqual(commands, [
59-
{ command: 'node ./scripts/deploy/deploy.ts prod v6 us3,us5,ap1,ap2,prtest00' },
60-
{ command: 'node ./scripts/deploy/upload-source-maps.ts v6 us3,us5,ap1,ap2,prtest00' },
69+
{ command: 'node ./scripts/deploy/deploy.ts prod v6 root' },
70+
{ command: 'node ./scripts/deploy/upload-source-maps.ts v6 root' },
6171
])
6272
})
6373
})
Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { parseArgs } from 'node:util'
22
import { printLog, runMain, timeout } from '../lib/executionUtils.ts'
33
import { command } from '../lib/command.ts'
4-
import { siteByDatacenter } from '../lib/datacenter.ts'
4+
import { getAllMinorDcs, getAllPrivateDcs } from '../lib/datacenter.ts'
55

66
/**
77
* Orchestrate the deployments of the artifacts for specific DCs
@@ -12,15 +12,6 @@ const ONE_MINUTE_IN_SECOND = 60
1212
const GATE_DURATION = 30 * ONE_MINUTE_IN_SECOND
1313
const GATE_INTERVAL = ONE_MINUTE_IN_SECOND
1414

15-
// Major DCs are the ones that are deployed last.
16-
// They have their own step jobs in `deploy-manual.yml` and `deploy-auto.yml`.
17-
const MAJOR_DCS = ['root', 'us1', 'eu1']
18-
19-
// Minor DCs are all the DCs from `siteByDatacenter` that are not in `MAJOR_DCS`.
20-
function getAllMinorDcs(): string[] {
21-
return Object.keys(siteByDatacenter).filter((dc) => !MAJOR_DCS.includes(dc))
22-
}
23-
2415
if (!process.env.NODE_TEST_CONTEXT) {
2516
runMain(() => main(...process.argv.slice(2)))
2617
}
@@ -42,30 +33,56 @@ export async function main(...args: string[]): Promise<void> {
4233
})
4334

4435
const version = positionals[0]
45-
const uploadPath = positionals[1] === 'minor-dcs' ? getAllMinorDcs().join(',') : positionals[1]
36+
const datacenters = getDatacenters(positionals[1])
4637

47-
if (!uploadPath) {
48-
throw new Error('UPLOAD_PATH argument is required')
38+
if (!datacenters) {
39+
throw new Error('DATACENTER argument is required')
4940
}
5041

5142
if (checkMonitors) {
52-
command`node ./scripts/deploy/check-monitors.ts ${uploadPath}`.withLogs().run()
43+
command`node ./scripts/deploy/check-monitors.ts ${datacenters.join(',')}`.withLogs().run()
5344
}
5445

55-
command`node ./scripts/deploy/deploy.ts prod ${version} ${uploadPath}`.withLogs().run()
56-
command`node ./scripts/deploy/upload-source-maps.ts ${version} ${uploadPath}`.withLogs().run()
46+
const uploadPathTypes = toDatacenterUploadPathType(datacenters).join(',')
5747

58-
if (checkMonitors && uploadPath !== 'root') {
59-
await gateMonitors(uploadPath)
48+
command`node ./scripts/deploy/deploy.ts prod ${version} ${uploadPathTypes}`.withLogs().run()
49+
command`node ./scripts/deploy/upload-source-maps.ts ${version} ${uploadPathTypes}`.withLogs().run()
50+
51+
if (checkMonitors) {
52+
await gateMonitors(datacenters)
6053
}
6154
}
6255

63-
async function gateMonitors(uploadPath: string): Promise<void> {
64-
printLog(`Check monitors for ${uploadPath} during ${GATE_DURATION / ONE_MINUTE_IN_SECOND} minutes`)
56+
async function gateMonitors(datacenters: string[]): Promise<void> {
57+
printLog(`Check monitors for ${datacenters.join(',')} during ${GATE_DURATION / ONE_MINUTE_IN_SECOND} minutes`)
58+
6559
for (let i = 0; i < GATE_DURATION; i += GATE_INTERVAL) {
66-
command`node ./scripts/deploy/check-monitors.ts ${uploadPath}`.run()
60+
command`node ./scripts/deploy/check-monitors.ts ${datacenters.join(',')}`.run()
6761
process.stdout.write('.') // progress indicator
6862
await timeout(GATE_INTERVAL * 1000)
6963
}
64+
7065
printLog() // new line
7166
}
67+
68+
function getDatacenters(datacenterGroup: string): string[] {
69+
if (datacenterGroup === 'minor-dcs') {
70+
return getAllMinorDcs()
71+
}
72+
73+
if (datacenterGroup === 'private-regions') {
74+
return getAllPrivateDcs()
75+
}
76+
77+
return datacenterGroup.split(',')
78+
}
79+
80+
function toDatacenterUploadPathType(datacenters: string[]): string[] {
81+
return datacenters.map((datacenter) => {
82+
if (datacenter === 'gov') {
83+
return 'root'
84+
}
85+
86+
return datacenter
87+
})
88+
}

‎scripts/deploy/lib/testHelpers.ts‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ export function mockCommandImplementation(mockFn: Mock<(...args: any[]) => void>
6262
withCurrentWorkingDirectory: () => result,
6363
withLogs: () => result,
6464
run(): string | undefined {
65-
commands.push(commandDetail)
66-
67-
if (command.includes('aws sts assume-role')) {
65+
if (command.startsWith('aws sts assume-role')) {
6866
return JSON.stringify({
6967
Credentials: {
7068
AccessKeyId: FAKE_AWS_ENV_CREDENTIALS.AWS_ACCESS_KEY_ID,
@@ -73,6 +71,22 @@ export function mockCommandImplementation(mockFn: Mock<(...args: any[]) => void>
7371
},
7472
})
7573
}
74+
75+
if (command.startsWith('ddtool datacenters list')) {
76+
return JSON.stringify([
77+
{ name: 'ap1.prod.dog', site: 'ap1.datadoghq.com' },
78+
{ name: 'ap2.prod.dog', site: 'ap2.datadoghq.com' },
79+
{ name: 'eu1.prod.dog', site: 'datadoghq.eu' },
80+
{ name: 'us1.prod.dog', site: 'datadoghq.com' },
81+
{ name: 'us3.prod.dog', site: 'us3.datadoghq.com' },
82+
{ name: 'us5.prod.dog', site: 'us5.datadoghq.com' },
83+
{ name: 'prtest00.prod.dog', site: 'prtest00.datadoghq.com' },
84+
{ name: 'prtest01.prod.dog', site: 'prtest01.datadoghq.com' },
85+
])
86+
}
87+
88+
// don't push command details for the above mock commands
89+
commands.push(commandDetail)
7690
},
7791
}
7892
return result

‎scripts/deploy/upload-source-maps.spec.ts‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from 'node:assert/strict'
22
import path from 'node:path'
3-
import { beforeEach, before, describe, it, mock } from 'node:test'
4-
import { siteByDatacenter } from '../lib/datacenter.ts'
3+
import { beforeEach, before, describe, it, mock, afterEach } from 'node:test'
4+
import { getAllDatacenters, getSite } from '../lib/datacenter.ts'
55
import { mockModule, mockCommandImplementation, replaceChunkHashes } from './lib/testHelpers.ts'
66

77
const FAKE_API_KEY = 'FAKE_API_KEY'
@@ -49,9 +49,13 @@ describe('upload-source-maps', () => {
4949
commands = mockCommandImplementation(commandMock)
5050
})
5151

52+
afterEach(() => {
53+
mock.restoreAll()
54+
})
55+
5256
function forEachDatacenter(callback: (site: string) => void): void {
53-
for (const site of Object.values(siteByDatacenter)) {
54-
callback(site)
57+
for (const datacenter of getAllDatacenters()) {
58+
callback(getSite(datacenter))
5559
}
5660
}
5761

‎scripts/deploy/upload-source-maps.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { printLog, runMain } from '../lib/executionUtils.ts'
33
import { command } from '../lib/command.ts'
44
import { getBuildEnvValue } from '../lib/buildEnv.ts'
55
import { getTelemetryOrgApiKey } from '../lib/secrets.ts'
6-
import { siteByDatacenter } from '../lib/datacenter.ts'
6+
import { getSite, getAllDatacenters } from '../lib/datacenter.ts'
77
import { forEachFile } from '../lib/filesUtils.ts'
88
import { buildRootUploadPath, buildDatacenterUploadPath, buildBundleFolder, packages } from './lib/deploymentUtils.ts'
99

@@ -20,7 +20,8 @@ function getSitesByVersion(version: string): string[] {
2020
case 'canary':
2121
return ['datadoghq.com']
2222
default:
23-
return Object.values(siteByDatacenter)
23+
// TODO: do we upload to root for all DCs?
24+
return getAllDatacenters().map(getSite)
2425
}
2526
}
2627

@@ -56,7 +57,7 @@ async function uploadSourceMaps(
5657
uploadPath = buildRootUploadPath(packageName, version)
5758
await renameFilesWithVersionSuffix(bundleFolder, version)
5859
} else {
59-
sites = [siteByDatacenter[uploadPathType]]
60+
sites = [getSite(uploadPathType)]
6061
uploadPath = buildDatacenterUploadPath(uploadPathType, packageName, version)
6162
}
6263
const prefix = path.dirname(`/${uploadPath}`)

0 commit comments

Comments
 (0)