Skip to content

Commit

Permalink
feat: write publishing timestamps to SSM (#1773)
Browse files Browse the repository at this point in the history
* feat: write publishing timestamps to SSM

Add a feature to allow publishing the latest published version and its
timestamp to SSM, so that we can start tracking how long it takes to
replicate, and alarm at a different severity if a canary fails
and we recently released.

* Add test

* Update test scripts

* MOve commands

* Add test

* chore: self mutation

Signed-off-by: github-actions <[email protected]>

* Ensure that the scripts don't drift

* Messaging

---------

Signed-off-by: github-actions <[email protected]>
Co-authored-by: github-actions <[email protected]>
  • Loading branch information
rix0rrr and github-actions authored Nov 25, 2024
1 parent 4e56a82 commit cc3f61c
Show file tree
Hide file tree
Showing 25 changed files with 449 additions and 82 deletions.
7 changes: 6 additions & 1 deletion .projen/tasks.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .projenrc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ const bundlePackageIntegrity = project.addTask('bundle:package-integrity', {

project.compileTask.spawn(bundlePackageIntegrity);

// Make sure that all "update-ssm" scripts are the same, so that they don't drift.
project.preCompileTask.exec(`for a in lib/publishing/*/update-ssm.sh; do
for b in lib/publishing/*/update-ssm.sh; do
if ! diff $a $b; then
echo "Files should be the same but are not:\n- $a\n- $b"
exit 1
fi
done
done`);

// The npmignore file includes original source files, which is undesirable.
project.npmignore?.exclude(
'/lib/**/*.ts',
Expand Down
13 changes: 7 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,18 @@ yarn test
```

Besides this, there is a delivlib instance deployed to an AWS account (712950704752) that configures a delivlib pipeline for
the package [aws-delivlib-sample](https://github.com/awslabs/aws-delivlib-sample). This instance can be used to test and
validate your local changes. To do this,
the package [aws-delivlib-sample](https://github.com/awslabs/aws-delivlib-sample).

1. Build the package - `yarn compile`
2. Setup credentials to our AWS account: 712950704752
3. Execute `yarn integ:update`. This will update the delivlib instance and the command will halt at a user prompt.
You should use this code to validate more elaborate changes to the Delivlib code base. To do this,

1. Setup credentials to our AWS account: 712950704752
2. Execute `yarn integ:update`. This will update the delivlib instance.

At this point, you will find the resources created by delivlib in the stack whose ARN is printed to the console. Wait for the
deployment to complete, and are then free to test and verify that your changes had the intended effect.

Once complete, continue following the instructions and prompts until the end.q
> NOTE: you might need to manually replicate the CDKlabs credentials to the publishing account. We don't do
> this often enough to make it worthwhile investing into automation for it.
## Releasing a New Version

Expand Down
20 changes: 0 additions & 20 deletions build-pipeline.sh

This file was deleted.

68 changes: 68 additions & 0 deletions lib/__tests__/publishing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,72 @@ describe('with standard pipeline', () => {
}]),
});
});

test.each(['npm', 'nuget', 'maven', 'pypi'] as const)('publishing SSM timestamps adds IAM permissions: %p', (type) => {
switch (type) {
case 'npm':
pipeline.publishToNpm({
npmTokenSecret: { secretArn: 'arn:secret' },
ssmPrefix: '/published/jsii-sample/npm',
});
break;

case 'nuget':
pipeline.publishToNuGet({
nugetApiKeySecret: { secretArn: 'arn:secret' },
ssmPrefix: '/published/jsii-sample/nuget',
});
break;

case 'maven':
const signingKey = new delivlib.OpenPGPKeyPair(stack, 'CodeSign', {
email: '[email protected]',
encryptionKey: new kms.Key(stack, 'CodeSign-CMK'),
expiry: '4y',
identity: 'aws-cdk-dev',
keySizeBits: 4_096,
pubKeyParameterName: `/${stack.node.path}/CodeSign.pub`,
secretName: stack.node.path + '/CodeSign',
version: 0,
removalPolicy: delivlib.OpenPGPKeyPairRemovalPolicy.DESTROY_IMMEDIATELY,
});

pipeline.publishToMaven({
mavenLoginSecret: { secretArn: 'arn:secret' },
mavenEndpoint: 'https://aws.oss.sonatype.org:443/',
stagingProfileId: '68a05363083174',
ssmPrefix: '/published/jsii-sample/maven',
signingKey,
});
break;

case 'pypi':
pipeline.publishToPyPI({
loginSecret: { secretArn: 'arn:secret' },
ssmPrefix: '/published/jsii-sample/pypi',
});
break;
}

const template = Template.fromStack(stack);
template.hasResourceProperties('AWS::IAM::Policy', {
PolicyDocument: {
Statement: Match.arrayWith([{
Effect: 'Allow',
Action: ['ssm:PutParameter', 'ssm:GetParameter'],
Resource: {
'Fn::Join': ['', [
'arn:',
{ Ref: 'AWS::Partition' },
':ssm:',
{ Ref: 'AWS::Region' },
':',
{ Ref: 'AWS::AccountId' },
`:parameter/published/jsii-sample/${type}/*`,
]],
},
}]),
},
});
});
});
36 changes: 5 additions & 31 deletions lib/__tests__/run-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,16 @@
set -euo pipefail
scriptdir=$(cd $(dirname $0) && pwd)

cdk_app="${scriptdir}/integ.delivlib.js"
expected="${scriptdir}/expected.yml"
actual="/tmp/actual.json"
cdk_app="npx ts-node lib/__tests__/integ.delivlib.ts"

echo "I have disabled snapshot tests here and I'm not apologizing for it [- huijbers@]"
exit 0

custom_stack_name="${TEST_STACK_NAME:-}"

export TEST_STACK_NAME="delivlib-test"

if [ "${1:-}" == "synth" ]; then
npx cdk --no-version-reporting -a ${cdk_app} synth
if [ "${1:-}" == "diff" ]; then
echo "I have disabled snapshot tests here and I'm not apologizing for it [- huijbers@]"
exit 0
fi

npx cdk --no-version-reporting --no-asset-metadata -a ${cdk_app} synth > ${actual}
export TEST_STACK_NAME="delivlib-test"

if [ "${1:-}" == "update" ]; then
npx cdk --no-version-reporting -a ${cdk_app} deploy ${2:-} ${3:-} ${4:-}
npx cdk --no-version-reporting -a "${cdk_app}" deploy ${2:-} ${3:-} ${4:-}
echo "Stack deployed, now, go to the console and wait for the pipeline to fully stabalize"
echo "Press ENTER to confirm that pipeline is green"
read
echo "Okay, now go to CFN console and delete the test stack ${TEST_STACK_NAME}"
echo "Press ENTER to confirm that the stack has been deleted"
read
cp -f ${actual} ${expected}
fi

if [ "${1:-}" == "force" ]; then
cp -f ${actual} ${expected}
fi

diff ${actual} ${expected} || {
echo "Expected test stack template does not match synthesized output"
echo "To update expectations: 'yarn integ:update'"
echo "(or if you trust the changes, './lib/__tests__/run-test.sh force')"
exit 1
}
31 changes: 25 additions & 6 deletions lib/__tests__/test-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,16 @@ export class TestStack extends Stack {
scriptDirectory: path.join(testDir, 'linux'),
});

// add a test that runs on Windows
pipeline.addTest('HelloWindows', {
platform: delivlib.ShellPlatform.Windows,
entrypoint: 'test.ps1',
scriptDirectory: path.join(testDir, 'windows'),
});
// This test takes a lot of time (~10 minutes), which is annoying during testing
const WINDOWS = false;
if (WINDOWS) {
// add a test that runs on Windows
pipeline.addTest('HelloWindows', {
platform: delivlib.ShellPlatform.Windows,
entrypoint: 'test.ps1',
scriptDirectory: path.join(testDir, 'windows'),
});
}

const externalId = 'require-me-please';

Expand Down Expand Up @@ -111,9 +115,13 @@ export class TestStack extends Stack {
// PUBLISH
//

const dryRun = false;

pipeline.publishToNpm({
npmTokenSecret: { secretArn: 'arn:aws:secretsmanager:us-east-1:712950704752:secret:delivlib/npm-MhaWgx' },
access: delivlib.NpmAccess.RESTRICTED,
ssmPrefix: '/published/jsii-sample/npm',
dryRun,
});

// this creates a self-signed certificate
Expand All @@ -133,6 +141,8 @@ export class TestStack extends Stack {
pipeline.publishToNuGet({
nugetApiKeySecret: { secretArn: 'arn:aws:secretsmanager:us-east-1:712950704752:secret:delivlib/nuget-jDbgrN' },
codeSign,
ssmPrefix: '/published/jsii-sample/nuget',
dryRun,
});

const signingKey = new delivlib.OpenPGPKeyPair(this, 'CodeSign', {
Expand All @@ -152,20 +162,27 @@ export class TestStack extends Stack {
mavenEndpoint: 'https://aws.oss.sonatype.org:443/',
signingKey,
stagingProfileId: '68a05363083174',
ssmPrefix: '/published/jsii-sample/maven',
dryRun,
});

pipeline.publishToGitHub({
githubRepo,
signingKey,
additionalInputArtifacts: shellableArtifacts,
ssmPrefix: '/published/jsii-sample/github',
dryRun,
});

pipeline.publishToGitHubPages({
githubRepo,
dryRun,
});

pipeline.publishToPyPI({
loginSecret: { secretArn: 'arn:aws:secretsmanager:us-east-1:712950704752:secret:delivlib/pypi-tp8M57' },
ssmPrefix: '/published/jsii-sample/pypi',
dryRun,
});

// publish go bindings to awslabs/aws-delivlib-sample under the "golang"
Expand All @@ -175,6 +192,8 @@ export class TestStack extends Stack {
gitBranch: 'golang',
gitUserEmail: '[email protected]',
gitUserName: 'Delivlib Tests',
ssmPrefix: '/published/jsii-sample/golang',
dryRun,
});

//
Expand Down
Loading

0 comments on commit cc3f61c

Please sign in to comment.