Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/update-cta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Update greeting CTA
on:
push:
branches:
- main
paths:
- config/cta.conf.js
workflow_dispatch:
inputs:
dry-run:
description: Run the script without updating the CTA
type: boolean
required: false
default: false
environment:
description: The environment to run the script in - must have the DOWNLOAD_CENTER_AWS_KEY and DOWNLOAD_CENTER_AWS_SECRET secrets configured
type: environment
required: true
default: CTA-Production

jobs:
dry-run:
name: Update greeting CTA
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'CTA-Production'}}
env:
npm_config_loglevel: verbose
npm_config_foreground_scripts: "true"
PUPPETEER_SKIP_DOWNLOAD: "true"
DOWNLOAD_CENTER_AWS_KEY: ${{ secrets.DOWNLOAD_CENTER_AWS_KEY }}
DOWNLOAD_CENTER_AWS_SECRET: ${{ secrets.DOWNLOAD_CENTER_AWS_SECRET }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ^20.x
cache: "npm"

- name: Install Dependencies and Compile
run: |
npm ci
npm run compile

- name: Update greeting CTA
run: |
npm run update-cta ${{ github.event.inputs.dry-run && '-- --dry-run' || '' }}
21 changes: 21 additions & 0 deletions config/cta.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';

module.exports = {
awsAccessKeyId: process.env.DOWNLOAD_CENTER_AWS_KEY,
awsSecretAccessKey: process.env.DOWNLOAD_CENTER_AWS_SECRET,
ctas: {
// Define the ctas per version here. '*' is the default cta which will be shown if there's no specific cta
// for the current version.
// '*': {
// chunks: [
// { text: 'Example', style: 'bold' },
// ]
// },
// '1.2.3': {
// chunks: [
// { text: 'Example', style: 'mongosh:uri' },
// ]
// }
},
isDryRun: false,
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"compile-all": "npm run compile-compass && npm run compile-exec",
"evergreen-release": "cd packages/build && npm run evergreen-release --",
"release": "cd packages/build && npm run release --",
"update-cta": "cd packages/build && npm run update-cta --",
"report-missing-help": "npm run report-missing-help --workspace @mongosh/shell-api",
"report-supported-api": "npm run report-supported-api --workspace @mongosh/shell-api",
"post-process-nyc": "ts-node scripts/nyc/post-process-nyc-output.ts",
Expand Down
3 changes: 2 additions & 1 deletion packages/build/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"publish": "ts-node src/index.ts publish",
"bump-auxiliary": "ts-node src/index.ts bump --auxiliary",
"publish-auxiliary": "ts-node src/index.ts publish --auxiliary",
"reformat": "npm run prettier -- --write . && npm run eslint --fix"
"reformat": "npm run prettier -- --write . && npm run eslint --fix",
"update-cta": "ts-node src/index.ts update-cta"
},
"license": "Apache-2.0",
"publishConfig": {
Expand Down
223 changes: 223 additions & 0 deletions packages/build/src/download-center/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
getUpdatedDownloadCenterConfig,
createAndPublishDownloadCenterConfig,
createJsonFeedEntry,
updateJsonFeedCTA,
} from './config';
import type { UpdateCTAConfig, JsonFeed } from './config';
import { promises as fs } from 'fs';
import path from 'path';
import fetch from 'node-fetch';
Expand Down Expand Up @@ -529,4 +531,225 @@ describe('DownloadCenter config', function () {
expect(serverTargets).to.include(target);
});
});

describe('updateJsonFeedCTA', function () {
let dlCenter: sinon.SinonStub | DownloadCenterConfig;
let uploadConfig: sinon.SinonStub;
let downloadConfig: sinon.SinonStub;
let uploadAsset: sinon.SinonStub;
let downloadAsset: sinon.SinonStub;

const existingUploadedJsonFeed = require(path.resolve(
__dirname,
'..',
'..',
'test',
'fixtures',
'cta-versions.json'
)) as JsonFeed;

const getConfig = (ctas: UpdateCTAConfig['ctas']): UpdateCTAConfig => {
return {
ctas,
isDryRun: false,
awsAccessKeyId: 'accessKey',
awsSecretAccessKey: 'secretKey',
};
};

const getUploadedJsonFeed = (): JsonFeed => {
return JSON.parse(uploadAsset.lastCall.args[1]) as JsonFeed;
};

beforeEach(function () {
uploadConfig = sinon.stub();
downloadConfig = sinon.stub();
uploadAsset = sinon.stub();
downloadAsset = sinon.stub();
dlCenter = sinon.stub();

downloadAsset.returns(JSON.stringify(existingUploadedJsonFeed));

dlCenter.returns({
downloadConfig,
uploadConfig,
uploadAsset,
downloadAsset,
});
});

for (const dryRun of [false, true]) {
it(`when dryRun is ${dryRun}, does ${
dryRun ? 'not ' : ''
}upload the updated json feed`, async function () {
const config = getConfig({
'1.10.3': {
chunks: [{ text: 'Foo' }],
},
'*': {
chunks: [{ text: 'Bar' }],
},
});

config.isDryRun = dryRun;

await updateJsonFeedCTA(config, dlCenter);
if (dryRun) {
expect(uploadAsset).to.not.have.been.called;
} else {
expect(uploadAsset).to.have.been.called;

const updatedJsonFeed = getUploadedJsonFeed();
expect(updatedJsonFeed.cta?.chunks).to.deep.equal([{ text: 'Bar' }]);
expect(
updatedJsonFeed.versions.filter((v) => v.version === '1.10.3')[0]
.cta?.chunks
).to.deep.equal([{ text: 'Foo' }]);
expect(
updatedJsonFeed.versions.filter((v) => v.version === '1.10.4')[0]
.cta
).to.be.undefined;
}
});
}

it('cannot add new versions', async function () {
expect(
existingUploadedJsonFeed.versions.filter((v) => v.version === '1.10.5')
).to.have.lengthOf(0);

const config = getConfig({
'1.10.5': {
chunks: [{ text: 'Foo' }],
},
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(
updatedJsonFeed.versions.filter((v) => v.version === '1.10.5')
).to.have.lengthOf(0);
});

it('can remove global cta', async function () {
// Preserve existing CTAs, but omit the global one
const ctas = (existingUploadedJsonFeed.versions as any[]).reduce(
(acc, current) => {
acc[current.version] = current.cta;
return acc;
},
{}
);
const config = getConfig(ctas);

expect(config.ctas['*']).to.be.undefined;
await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(updatedJsonFeed.cta).to.be.undefined;
});

it('can remove version specific cta', async function () {
expect(
existingUploadedJsonFeed.versions.map((v) => v.cta).filter((cta) => cta)
).to.have.length.greaterThan(0);

const config = getConfig({
'*': existingUploadedJsonFeed.cta!,
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();
expect(updatedJsonFeed.cta).to.not.be.undefined;
expect(
updatedJsonFeed.versions.map((v) => v.cta).filter((cta) => cta)
).to.have.lengthOf(0);
});

it('can update global cta', async function () {
const config = getConfig({
'*': {
chunks: [{ text: "It's a beautiful day", style: 'imagePositive' }],
},
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(updatedJsonFeed.cta).to.deep.equal({
chunks: [{ text: "It's a beautiful day", style: 'imagePositive' }],
});
});

it('can update version-specific cta', async function () {
const config = getConfig({
'1.10.3': {
chunks: [{ text: "It's a beautiful day", style: 'imagePositive' }],
},
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(
updatedJsonFeed.versions.filter((v) => v.version === '1.10.3')[0].cta
).to.deep.equal({
chunks: [{ text: "It's a beautiful day", style: 'imagePositive' }],
});
});

it('can add global cta', async function () {
// Remove the existing cta
existingUploadedJsonFeed.cta = undefined;

const config = getConfig({
'*': {
chunks: [
{ text: 'Go outside and enjoy the sun', style: 'imagePositive' },
],
},
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(updatedJsonFeed.cta).to.deep.equal({
chunks: [
{ text: 'Go outside and enjoy the sun', style: 'imagePositive' },
],
});
});

it('can add version-specific cta', async function () {
// Remove the existing cta
existingUploadedJsonFeed.cta = undefined;

const config = getConfig({
'1.10.4': {
chunks: [
{ text: 'Go outside and enjoy the sun', style: 'imagePositive' },
],
},
});

await updateJsonFeedCTA(config, dlCenter);

const updatedJsonFeed = getUploadedJsonFeed();

expect(
updatedJsonFeed.versions.filter((v) => v.version === '1.10.4')[0].cta
).to.deep.equal({
chunks: [
{ text: 'Go outside and enjoy the sun', style: 'imagePositive' },
],
});
});
});
});
Loading