Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for fetching a greeting CTA as part of the update flow MONGOSH-1897 #2254

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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 configs/eslint-config-mongosh/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ module.exports = {
...common.testRules,
...extraJSRules,
...extraTypescriptRules,
'@typescript-eslint/no-non-null-assertion': 'off',
},
},
],
Expand Down
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 @@ -26,7 +26,8 @@
"evergreen-release": "ts-node -r ../../scripts/import-expansions.js src/index.ts",
"release": "ts-node src/index.ts trigger-release",
"prettier": "prettier",
"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
224 changes: 224 additions & 0 deletions packages/build/src/download-center/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {
getUpdatedDownloadCenterConfig,
createAndPublishDownloadCenterConfig,
createJsonFeedEntry,
updateJsonFeedCTA,
UpdateCTAConfig,
JsonFeed,
} from './config';
import { promises as fs } from 'fs';
import path from 'path';
Expand Down Expand Up @@ -529,4 +532,225 @@ describe('DownloadCenter config', function () {
expect(serverTargets).to.include(target);
});
});

describe('updateJsonFeedCTA', function () {
let dlCenter: any;
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 (let 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
Loading