Skip to content

Commit ef550a0

Browse files
rix0rrrgithub-actions
and
github-actions
authored
feat: record CLI version in manifest package (#184)
Record the current CLI version in the manifest package when we release the manifest. This by itself will not trigger a new release of the `cloud-assembly-schema` package, so the version only gets recorded (and published!) when there is a new version of `cloud-assembly-schema` to publish anyway, and the version will only be displayed back to the user if there is an incompatibility of the major version number. That means we won't necessarily show the *lowest* possible CLI version number when the user needs to upgrade, but we'll show a valid CLI version number that will definitely support the given manifest. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license --------- Signed-off-by: github-actions <[email protected]> Co-authored-by: github-actions <[email protected]>
1 parent a6d4516 commit ef550a0

File tree

7 files changed

+89
-5
lines changed

7 files changed

+89
-5
lines changed

.projenrc.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,17 @@ new JsiiBuild(cloudAssemblySchema, {
376376
(() => {
377377
cloudAssemblySchema.preCompileTask.exec('tsx projenrc/update.ts');
378378

379+
// This file will be generated at release time. It needs to be gitignored or it will
380+
// fail projen's "no tamper" check, which means it must also be generated every build time.
381+
//
382+
// Crucially, this must also run during release after bumping, but that is satisfied already
383+
// by making it part of preCompile, because that makes it run as part of projen build.
384+
cloudAssemblySchema.preCompileTask.exec('tsx ../../../projenrc/copy-cli-version-to-assembly.task.ts');
385+
cloudAssemblySchema.gitignore.addPatterns('cli-version.json');
386+
379387
cloudAssemblySchema.addPackageIgnore('*.ts');
380388
cloudAssemblySchema.addPackageIgnore('!*.d.ts');
381-
cloudAssemblySchema.addPackageIgnore('** /scripts');
389+
cloudAssemblySchema.addPackageIgnore('**/scripts');
382390
})();
383391

384392
//////////////////////////////////////////////////////////////////////

packages/@aws-cdk/cloud-assembly-schema/.gitignore

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/cloud-assembly-schema/.npmignore

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/cloud-assembly-schema/.projen/tasks.json

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/@aws-cdk/cloud-assembly-schema/lib/manifest.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ import * as integ from './integ-tests';
1313
// see exec.ts#createAssembly
1414
export const VERSION_MISMATCH: string = 'Cloud assembly schema version mismatch';
1515

16+
/**
17+
* CLI version is created at build and release time
18+
*
19+
* It needs to be .gitignore'd, otherwise the projen 'no uncommitted
20+
* changes' self-check will fail, which means it needs to be generated
21+
* at build time if it doesn't already exist.
22+
*/
23+
import CLI_VERSION = require('../cli-version.json');
24+
1625
import ASSETS_SCHEMA = require('../schema/assets.schema.json');
1726

1827
import ASSEMBLY_SCHEMA = require('../schema/cloud-assembly.schema.json');
@@ -141,6 +150,14 @@ export class Manifest {
141150
return `${SCHEMA_VERSION.revision}.0.0`;
142151
}
143152

153+
/**
154+
* Return the CLI version that supports this Cloud Assembly Schema version
155+
*/
156+
public static cliVersion(): string | undefined {
157+
const version = CLI_VERSION.version;
158+
return version ? version : undefined;
159+
}
160+
144161
/**
145162
* Deprecated
146163
* @deprecated use `saveAssemblyManifest()`
@@ -216,7 +233,11 @@ export class Manifest {
216233
schema: jsonschema.Schema,
217234
preprocess?: (obj: any) => any,
218235
) {
219-
let withVersion = { ...manifest, version: Manifest.version() };
236+
let withVersion = {
237+
...manifest,
238+
version: Manifest.version(),
239+
minimumCliVersion: Manifest.cliVersion(),
240+
} satisfies assembly.AssemblyManifest;
220241
Manifest.validate(withVersion, schema);
221242
if (preprocess) {
222243
withVersion = preprocess(withVersion);

packages/@aws-cdk/cloud-assembly-schema/test/manifest.test.ts

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @typescript-eslint/no-require-imports */
12
import * as fs from 'fs';
23
import * as os from 'os';
34
import * as path from 'path';
@@ -31,10 +32,36 @@ test('manifest save', () => {
3132

3233
const saved = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' }));
3334

34-
expect(saved).toEqual({
35+
expect(saved).toEqual(expect.objectContaining({
3536
...assemblyManifest,
3637
version: Manifest.version(), // version is forced
37-
});
38+
}));
39+
});
40+
41+
test('manifest contains minimum CLI version', () => {
42+
const outdir = fs.mkdtempSync(path.join(os.tmpdir(), 'schema-tests'));
43+
const manifestFile = path.join(outdir, 'manifest.json');
44+
45+
// This relies on the fact that the cli JSON version file is `require()`d,
46+
// and that the 'require' below will find the same object in the module cache.
47+
const cliVersionFile = require(`${__dirname}/../cli-version.json`);
48+
cliVersionFile.version = '9.9.9';
49+
try {
50+
const assemblyManifest: AssemblyManifest = {
51+
version: 'version',
52+
runtime: {
53+
libraries: { lib1: '1.2.3' },
54+
},
55+
};
56+
57+
Manifest.saveAssemblyManifest(assemblyManifest, manifestFile);
58+
59+
const saved = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' }));
60+
61+
expect(saved.minimumCliVersion).toEqual('9.9.9');
62+
} finally {
63+
cliVersionFile.version = '';
64+
}
3865
});
3966

4067
test('assumeRoleAdditionalOptions.RoleArn is validated in stack artifact', () => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { promises as fs } from 'fs';
2+
3+
/**
4+
* Copy the version from the CLI into the `@aws-cdk/cloud-assembly-schema` package at release time.
5+
*/
6+
async function main() {
7+
const cliVersion = JSON.parse(await fs.readFile(`${__dirname}/../packages/aws-cdk/package.json`, 'utf8')).version;
8+
9+
const cliVersionFile = `${__dirname}/../packages/@aws-cdk/cloud-assembly-schema/cli-version.json`;
10+
11+
// We write an empty string if we're in "development mode" to show that we don't really have a version.
12+
// It's not a missing field so that the `import` statement of that JSON file in TypeScript
13+
// always knows the version field is there, and its value is a string.
14+
const advertisedVersion = cliVersion !== '0.0.0' ? cliVersion : '';
15+
16+
await fs.writeFile(cliVersionFile, JSON.stringify({ version: advertisedVersion }), 'utf8');
17+
}
18+
19+
main().catch(e => {
20+
// this is effectively a mini-cli
21+
// eslint-disable-next-line no-console
22+
console.error(e);
23+
process.exitCode = 1;
24+
});

0 commit comments

Comments
 (0)