|
| 1 | +import { Monorepo, TypeScriptWorkspace } from 'cdklabs-projen-project-types/lib/yarn'; |
| 2 | +import { Component, github } from 'projen'; |
| 3 | + |
| 4 | +export interface S3DocsPublishingProps { |
| 5 | + /** |
| 6 | + * The docs stream to publish to. |
| 7 | + */ |
| 8 | + readonly docsStream: string; |
| 9 | + |
| 10 | + /** |
| 11 | + * The path to the artifact in the dist folder |
| 12 | + */ |
| 13 | + readonly artifactPath: string; |
| 14 | + |
| 15 | + /** |
| 16 | + * The role arn (or github expression) for OIDC to assume to do the actual publishing. |
| 17 | + */ |
| 18 | + readonly roleToAssume: string; |
| 19 | + |
| 20 | + /** |
| 21 | + * The bucket name (or github expression) to publish to. |
| 22 | + */ |
| 23 | + readonly bucketName: string; |
| 24 | +} |
| 25 | + |
| 26 | +export class S3DocsPublishing extends Component { |
| 27 | + private readonly github: github.GitHub; |
| 28 | + private readonly props: S3DocsPublishingProps; |
| 29 | + |
| 30 | + constructor(project: TypeScriptWorkspace, props: S3DocsPublishingProps) { |
| 31 | + super(project); |
| 32 | + |
| 33 | + const gh = (project.parent! as Monorepo).github; |
| 34 | + if (!gh) { |
| 35 | + throw new Error('This workspace does not have a GitHub instance'); |
| 36 | + } |
| 37 | + this.github = gh; |
| 38 | + |
| 39 | + this.props = props; |
| 40 | + } |
| 41 | + |
| 42 | + public preSynthesize() { |
| 43 | + const releaseWf = this.github.tryFindWorkflow('release'); |
| 44 | + if (!releaseWf) { |
| 45 | + throw new Error('Could not find release workflow'); |
| 46 | + } |
| 47 | + |
| 48 | + const safeName = this.project.name.replace('@', '').replace('/', '-'); |
| 49 | + |
| 50 | + releaseWf.addJob(`${safeName}_release_docs`, { |
| 51 | + name: `${this.project.name}: Publish docs to S3`, |
| 52 | + environment: 'releasing', // <-- this has the configuration |
| 53 | + needs: [`${safeName}_release_npm`], |
| 54 | + runsOn: ['ubuntu-latest'], |
| 55 | + permissions: { |
| 56 | + idToken: github.workflows.JobPermission.WRITE, |
| 57 | + contents: github.workflows.JobPermission.READ, |
| 58 | + }, |
| 59 | + steps: [ |
| 60 | + { |
| 61 | + name: 'Download build artifacts', |
| 62 | + uses: 'actions/download-artifact@v4', |
| 63 | + with: { |
| 64 | + name: `${this.project.name}_build-artifact`, |
| 65 | + path: 'dist', |
| 66 | + }, |
| 67 | + }, |
| 68 | + { |
| 69 | + name: 'Authenticate Via OIDC Role', |
| 70 | + id: 'creds', |
| 71 | + uses: 'aws-actions/configure-aws-credentials@v4', |
| 72 | + with: { |
| 73 | + 'aws-region': 'us-east-1', |
| 74 | + 'role-duration-seconds': 14400, |
| 75 | + 'role-to-assume': '${{ vars.AWS_ROLE_TO_ASSUME_FOR_ACCOUNT }}', |
| 76 | + 'role-session-name': 'releasing@aws-cdk-cli', |
| 77 | + }, |
| 78 | + }, |
| 79 | + { |
| 80 | + name: 'Assume the publishing role', |
| 81 | + id: 'publishing-creds', |
| 82 | + uses: 'aws-actions/configure-aws-credentials@v4', |
| 83 | + with: { |
| 84 | + 'aws-region': 'us-east-1', |
| 85 | + 'role-duration-seconds': 14400, |
| 86 | + 'role-to-assume': this.props.roleToAssume, |
| 87 | + 'role-session-name': 's3publishing@aws-cdk-cli', |
| 88 | + 'role-chaining': true, |
| 89 | + }, |
| 90 | + }, |
| 91 | + { |
| 92 | + name: 'Publish docs', |
| 93 | + env: { |
| 94 | + BUCKET_NAME: this.props.bucketName, |
| 95 | + DOCS_STREAM: this.props.docsStream, |
| 96 | + }, |
| 97 | + run: [ |
| 98 | + '::add-mask::$BUCKET_NAME', // always hide bucket name |
| 99 | + |
| 100 | + // setup paths |
| 101 | + `echo "S3_PATH=$DOCS_STREAM/${safeName}-v$(cat dist/version.txt).zip" >> "$GITHUB_ENV"`, |
| 102 | + 'echo "S3_URI=s3://$BUCKET_NAME/$S3_PATH" >> "$GITHUB_ENV"', |
| 103 | + `echo "LATEST=latest-${this.props.docsStream}" >> "$GITHUB_ENV"`, |
| 104 | + |
| 105 | + // create the latest marker |
| 106 | + 'echo $S3_PATH > $LATEST', |
| 107 | + |
| 108 | + // check if the target file already exists and upload |
| 109 | + '(! aws s3 ls --human-readable $S3_URI \\', |
| 110 | + `&& aws s3 cp --dryrun dist/${this.props.artifactPath} $S3_URI \\`, |
| 111 | + '&& aws s3 cp --dryrun $LATEST s3://$BUCKET_NAME/$LATEST) \\', |
| 112 | + '|| (echo "Docs artifact already published, skipping upload")', |
| 113 | + ].join('\n'), |
| 114 | + }, |
| 115 | + ], |
| 116 | + }); |
| 117 | + } |
| 118 | +} |
0 commit comments