Skip to content

Commit 2a0955f

Browse files
committed
Wire up some basic cli commands for updating the cta
1 parent 43efe22 commit 2a0955f

File tree

8 files changed

+173
-61
lines changed

8 files changed

+173
-61
lines changed

config/cta.conf.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
module.exports = {
4+
awsAccessKeyId: process.env.DOWNLOAD_CENTER_AWS_KEY,
5+
awsSecretAccessKey: process.env.DOWNLOAD_CENTER_AWS_SECRET,
6+
ctas: {
7+
// Define the ctas per version here. '*' is the default cta which will be shown if there's no specific cta
8+
// for the current version.
9+
// '*': {
10+
// runs: [
11+
// { text: 'Example', style: 'bold' },
12+
// ]
13+
// },
14+
// '1.2.3': {
15+
// runs: [
16+
// { text: 'Example', style: 'mongosh:uri' },
17+
// ]
18+
// }
19+
},
20+
isDryRun: false,
21+
}

packages/build/src/download-center/config.ts

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
} from '@mongodb-js/dl-center/dist/download-center-config';
1010
import {
1111
ARTIFACTS_BUCKET,
12-
ARTIFACTS_FOLDER,
12+
JSON_FEED_ARTIFACT_KEY,
1313
ARTIFACTS_URL_PUBLIC_BASE,
1414
CONFIGURATION_KEY,
1515
CONFIGURATIONS_BUCKET,
@@ -32,6 +32,24 @@ import path from 'path';
3232
import semver from 'semver';
3333
import { hashListFiles } from '../run-download-and-list-artifacts';
3434

35+
async function getCurrentJsonFeed(
36+
dlcenterArtifacts: DownloadCenterCls
37+
): Promise<JsonFeed | undefined> {
38+
let existingJsonFeedText;
39+
try {
40+
existingJsonFeedText = await dlcenterArtifacts.downloadAsset(
41+
JSON_FEED_ARTIFACT_KEY
42+
);
43+
} catch (err: any) {
44+
console.warn('Failed to get existing JSON feed text', err);
45+
if (err?.code !== 'NoSuchKey') throw err;
46+
}
47+
48+
return existingJsonFeedText
49+
? JSON.parse(existingJsonFeedText.toString())
50+
: undefined;
51+
}
52+
3553
export async function createAndPublishDownloadCenterConfig(
3654
outputDir: string,
3755
packageInformation: PackageInformationProvider,
@@ -80,20 +98,8 @@ export async function createAndPublishDownloadCenterConfig(
8098
accessKeyId: awsAccessKeyId,
8199
secretAccessKey: awsSecretAccessKey,
82100
});
83-
const jsonFeedArtifactkey = `${ARTIFACTS_FOLDER}/mongosh.json`;
84-
let existingJsonFeedText;
85-
try {
86-
existingJsonFeedText = await dlcenterArtifacts.downloadAsset(
87-
jsonFeedArtifactkey
88-
);
89-
} catch (err: any) {
90-
console.warn('Failed to get existing JSON feed text', err);
91-
if (err?.code !== 'NoSuchKey') throw err;
92-
}
93101

94-
const existingJsonFeed: JsonFeed | undefined = existingJsonFeedText
95-
? JSON.parse(existingJsonFeedText.toString())
96-
: undefined;
102+
const existingJsonFeed = await getCurrentJsonFeed(dlcenterArtifacts);
97103
const injectedJsonFeed: JsonFeed | undefined = injectedJsonFeedFile
98104
? JSON.parse(await fs.readFile(injectedJsonFeedFile, 'utf8'))
99105
: undefined;
@@ -122,12 +128,42 @@ export async function createAndPublishDownloadCenterConfig(
122128
await Promise.all([
123129
dlcenter.uploadConfig(CONFIGURATION_KEY, config),
124130
dlcenterArtifacts.uploadAsset(
125-
jsonFeedArtifactkey,
131+
JSON_FEED_ARTIFACT_KEY,
126132
JSON.stringify(newJsonFeed, null, 2)
127133
),
128134
]);
129135
}
130136

137+
export async function updateJsonFeedCTA(
138+
config: UpdateCTAConfig,
139+
DownloadCenter: typeof DownloadCenterCls = DownloadCenterCls
140+
) {
141+
const dlcenterArtifacts = new DownloadCenter({
142+
bucket: ARTIFACTS_BUCKET,
143+
accessKeyId: config.awsAccessKeyId,
144+
secretAccessKey: config.awsSecretAccessKey,
145+
});
146+
147+
const jsonFeed = await getCurrentJsonFeed(dlcenterArtifacts);
148+
if (!jsonFeed) {
149+
throw new Error('No existing JSON feed found');
150+
}
151+
152+
jsonFeed.cta = config.ctas['*'];
153+
for (const version of jsonFeed.versions) {
154+
version.cta = config.ctas[version.version];
155+
}
156+
157+
const patchedJsonFeed = JSON.stringify(jsonFeed, null, 2);
158+
if (config.isDryRun) {
159+
console.warn('Not uploading JSON feed in dry-run mode');
160+
console.warn(`Patched JSON feed: ${patchedJsonFeed}`);
161+
return;
162+
}
163+
164+
await dlcenterArtifacts.uploadAsset(JSON_FEED_ARTIFACT_KEY, patchedJsonFeed);
165+
}
166+
131167
export function getUpdatedDownloadCenterConfig(
132168
downloadedConfig: DownloadCenterConfig,
133169
getVersionConfig: () => ReturnType<typeof createVersionConfig>
@@ -201,13 +237,32 @@ export function createVersionConfig(
201237
};
202238
}
203239

240+
// TODO: this is duplicated in update-notification-manager.ts
241+
interface GreetingCTADetails {
242+
chunks: {
243+
text: string;
244+
style: string; // TODO: this is actually clr.ts/StyleDefinition
245+
}[];
246+
}
247+
248+
export interface UpdateCTAConfig {
249+
ctas: {
250+
[version: string]: GreetingCTADetails;
251+
};
252+
awsAccessKeyId: string;
253+
awsSecretAccessKey: string;
254+
isDryRun: boolean;
255+
}
256+
204257
interface JsonFeed {
205258
versions: JsonFeedVersionEntry[];
259+
cta?: GreetingCTADetails;
206260
}
207261

208262
interface JsonFeedVersionEntry {
209263
version: string;
210264
downloads: JsonFeedDownloadEntry[];
265+
cta?: GreetingCTADetails;
211266
}
212267

213268
interface JsonFeedDownloadEntry {
@@ -275,6 +330,8 @@ function mergeFeeds(...args: (JsonFeed | undefined)[]): JsonFeed {
275330
if (index === -1) newFeed.versions.unshift(version);
276331
else newFeed.versions.splice(index, 1, version);
277332
}
333+
334+
newFeed.cta = feed?.cta ?? newFeed.cta;
278335
}
279336
newFeed.versions.sort((a, b) => semver.rcompare(a.version, b.version));
280337
return newFeed;

packages/build/src/download-center/constants.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,30 @@ const fallback = require('./fallback.json');
33
/**
44
* The S3 bucket for download center configurations.
55
*/
6-
export const CONFIGURATIONS_BUCKET = 'info-mongodb-com' as const;
6+
export const CONFIGURATIONS_BUCKET = 'info-mongodb-com';
77

88
/**
99
* The S3 object key for the download center configuration.
1010
*/
1111
export const CONFIGURATION_KEY =
12-
'com-download-center/mongosh.multiversion.json' as const;
12+
'com-download-center/mongosh.multiversion.json';
1313

1414
/**
1515
* The S3 bucket for download center artifacts.
1616
*/
17-
export const ARTIFACTS_BUCKET = 'downloads.10gen.com' as const;
17+
export const ARTIFACTS_BUCKET = 'downloads.10gen.com';
1818

1919
/**
2020
* The S3 "folder" for uploaded artifacts.
2121
*/
22-
export const ARTIFACTS_FOLDER = 'compass' as const;
22+
export const ARTIFACTS_FOLDER = 'compass';
23+
24+
/**
25+
* The S3 artifact key for the versions JSON feed.
26+
*/
27+
export const JSON_FEED_ARTIFACT_KEY = `${ARTIFACTS_FOLDER}/mongosh.json`;
2328

2429
export const ARTIFACTS_URL_PUBLIC_BASE =
25-
'https://downloads.mongodb.com/compass/' as const;
30+
'https://downloads.mongodb.com/compass/';
2631

2732
export const ARTIFACTS_FALLBACK = Object.freeze(fallback);

packages/build/src/index.ts

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import { triggerRelease } from './local';
66
import type { ReleaseCommand } from './release';
77
import { release } from './release';
88
import type { Config, PackageVariant } from './config';
9+
import { updateJsonFeedCTA, UpdateCTAConfig } from './download-center';
910

1011
export { getArtifactUrl, downloadMongoDb };
1112

12-
const validCommands: (ReleaseCommand | 'trigger-release')[] = [
13+
const validCommands: (ReleaseCommand | 'trigger-release' | 'update-cta')[] = [
1314
'bump',
1415
'compile',
1516
'package',
@@ -20,11 +21,12 @@ const validCommands: (ReleaseCommand | 'trigger-release')[] = [
2021
'download-crypt-shared-library',
2122
'download-and-list-artifacts',
2223
'trigger-release',
24+
'update-cta',
2325
] as const;
2426

2527
const isValidCommand = (
2628
cmd: string
27-
): cmd is ReleaseCommand | 'trigger-release' =>
29+
): cmd is ReleaseCommand | 'trigger-release' | 'update-cta' =>
2830
(validCommands as string[]).includes(cmd);
2931

3032
if (require.main === module) {
@@ -38,29 +40,46 @@ if (require.main === module) {
3840
);
3941
}
4042

41-
if (command === 'trigger-release') {
42-
await triggerRelease(process.argv.slice(3));
43-
} else {
44-
const config: Config = require(path.join(
45-
__dirname,
46-
'..',
47-
'..',
48-
'..',
49-
'config',
50-
'build.conf.js'
51-
));
43+
switch (command) {
44+
case 'trigger-release':
45+
await triggerRelease(process.argv.slice(3));
46+
break;
47+
case 'update-cta':
48+
const ctaConfig: UpdateCTAConfig = require(path.join(
49+
__dirname,
50+
'..',
51+
'..',
52+
'..',
53+
'config',
54+
'cta.conf.js'
55+
));
5256

53-
const cliBuildVariant = process.argv
54-
.map((arg) => /^--build-variant=(.+)$/.exec(arg))
55-
.filter(Boolean)[0];
56-
if (cliBuildVariant) {
57-
config.packageVariant = cliBuildVariant[1] as PackageVariant;
58-
validatePackageVariant(config.packageVariant);
59-
}
57+
ctaConfig.isDryRun ||= process.argv.includes('--dry-run');
6058

61-
config.isDryRun ||= process.argv.includes('--dry-run');
59+
await updateJsonFeedCTA(ctaConfig);
60+
break;
61+
default:
62+
const config: Config = require(path.join(
63+
__dirname,
64+
'..',
65+
'..',
66+
'..',
67+
'config',
68+
'build.conf.js'
69+
));
6270

63-
await release(command, config);
71+
const cliBuildVariant = process.argv
72+
.map((arg) => /^--build-variant=(.+)$/.exec(arg))
73+
.filter(Boolean)[0];
74+
if (cliBuildVariant) {
75+
config.packageVariant = cliBuildVariant[1] as PackageVariant;
76+
validatePackageVariant(config.packageVariant);
77+
}
78+
79+
config.isDryRun ||= process.argv.includes('--dry-run');
80+
81+
await release(command, config);
82+
break;
6483
}
6584
})().then(
6685
() => process.exit(0),

packages/cli-repl/src/mongosh-repl.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ class MongoshNodeRepl implements EvaluationListener {
182182
*/
183183
async initialize(
184184
serviceProvider: ServiceProvider,
185-
greeting: GreetingDetails
185+
greeting?: GreetingDetails
186186
): Promise<InitializationToken> {
187187
const usePlainVMContext = this.shellCliOptions.jsContext === 'plain-vm';
188188

@@ -582,7 +582,10 @@ class MongoshNodeRepl implements EvaluationListener {
582582
/**
583583
* The greeting for the shell, showing server and shell version.
584584
*/
585-
async greet(mongodVersion: string, greeting: GreetingDetails): Promise<void> {
585+
async greet(
586+
mongodVersion: string,
587+
greeting?: GreetingDetails
588+
): Promise<void> {
586589
this.output.write('sadfasdfasdfassafsa');
587590
this.output.write(JSON.stringify({ mongodVersion, greeting }) + '\n');
588591

@@ -598,7 +601,7 @@ class MongoshNodeRepl implements EvaluationListener {
598601
'Using Mongosh',
599602
'mongosh:section-header'
600603
)}:\t\t${version}\n`;
601-
if (greeting.moreRecentMongoshVersion) {
604+
if (greeting?.moreRecentMongoshVersion) {
602605
text += `mongosh ${this.clr(
603606
greeting.moreRecentMongoshVersion,
604607
'bold'
@@ -608,7 +611,7 @@ class MongoshNodeRepl implements EvaluationListener {
608611
)}\n`;
609612
}
610613

611-
if (greeting.currentVersionCTA) {
614+
if (greeting?.currentVersionCTA) {
612615
for (const run of greeting.currentVersionCTA) {
613616
text += this.clr(run.text, run.style);
614617
}

packages/cli-repl/src/update-notification-manager.spec.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,28 +41,33 @@ describe('UpdateNotificationManager', function () {
4141

4242
it('fetches and stores information about the current release', async function () {
4343
const manager = new UpdateNotificationManager();
44-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
44+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
4545
expect(await manager.getLatestVersionIfMoreRecent('')).to.equal(null);
4646
expect(reqHandler).to.have.been.calledOnce;
4747
const fileContents = JSON.parse(await fs.readFile(filename, 'utf-8'));
4848
expect(Object.keys(fileContents)).to.deep.equal([
4949
'updateURL',
5050
'lastChecked',
51+
'cta',
5152
]);
5253
expect(fileContents.lastChecked).to.be.a('number');
5354
});
5455

5556
it('uses existing data if some has been fetched recently', async function () {
5657
const manager = new UpdateNotificationManager();
57-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
58-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
58+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
59+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
5960
expect(reqHandler).to.have.been.calledOnce;
6061
});
6162

6263
it('does not re-use existing data if the updateURL value has changed', async function () {
6364
const manager = new UpdateNotificationManager();
64-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
65-
await manager.fetchUpdateMetadata(httpServerUrl + '/?foo=bar', filename);
65+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
66+
await manager.fetchUpdateMetadata(
67+
httpServerUrl + '/?foo=bar',
68+
filename,
69+
'1.2.3'
70+
);
6671
expect(reqHandler).to.have.been.calledTwice;
6772
});
6873

@@ -80,15 +85,15 @@ describe('UpdateNotificationManager', function () {
8085
res.end('{}');
8186
});
8287
const manager = new UpdateNotificationManager();
83-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
88+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
8489
await fs.writeFile(
8590
filename,
8691
JSON.stringify({
8792
...JSON.parse(await fs.readFile(filename, 'utf8')),
8893
lastChecked: 0,
8994
})
9095
);
91-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
96+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
9297
expect(reqHandler).to.have.been.calledTwice;
9398
expect(cacheHits).to.equal(1);
9499
});
@@ -106,7 +111,7 @@ describe('UpdateNotificationManager', function () {
106111
);
107112
});
108113
const manager = new UpdateNotificationManager();
109-
await manager.fetchUpdateMetadata(httpServerUrl, filename);
114+
await manager.fetchUpdateMetadata(httpServerUrl, filename, '1.2.3');
110115
expect(await manager.getLatestVersionIfMoreRecent('')).to.equal('1.1.0');
111116
expect(await manager.getLatestVersionIfMoreRecent('1.0.0')).to.equal(
112117
'1.1.0'

0 commit comments

Comments
 (0)