in projenrc/s3-docs-publishing.ts [60:150]
public preSynthesize() {
const releaseWf = this.github.tryFindWorkflow('release');
if (!releaseWf) {
throw new Error('Could not find release workflow');
}
const safeName = this.project.name.replace('@', '').replace('/', '-');
const isApiExtractor = this.props.docType === DocType.API_EXTRACTOR;
// Determine job ID, name suffix, S3 path based on doc type
const jobIdSuffix = isApiExtractor ? '_api_extractor' : '_typedoc';
const nameSuffix = isApiExtractor ? 'api-extractor' : 'typedoc';
const s3PathPrefix = isApiExtractor ? `${safeName}-api-model-v` : `${safeName}-v`;
releaseWf.addJob(`${safeName}_release${jobIdSuffix}`, {
name: `${this.project.name}: Publish ${nameSuffix} to S3`,
environment: 'releasing', // <-- this has the configuration
needs: [`${safeName}_release_npm`],
runsOn: ['ubuntu-latest'],
permissions: {
idToken: github.workflows.JobPermission.WRITE,
contents: github.workflows.JobPermission.READ,
},
steps: [
{
name: 'Download build artifacts',
uses: 'actions/download-artifact@v4',
with: {
name: `${safeName}_build-artifact`,
path: 'dist',
},
},
{
name: 'Authenticate Via OIDC Role',
id: 'creds',
uses: 'aws-actions/configure-aws-credentials@v4',
with: {
'aws-region': 'us-east-1',
'role-to-assume': '${{ vars.AWS_ROLE_TO_ASSUME_FOR_ACCOUNT }}',
'role-session-name': `s3-${isApiExtractor ? 'api-model-' : ''}docs-publishing@aws-cdk-cli`,
'mask-aws-account-id': true,
},
},
{
name: 'Assume the publishing role',
id: 'publishing-creds',
uses: 'aws-actions/configure-aws-credentials@v4',
with: {
'aws-region': 'us-east-1',
'role-to-assume': this.props.roleToAssume,
'role-session-name': `s3-${isApiExtractor ? 'api-model-' : ''}docs-publishing@aws-cdk-cli`,
'mask-aws-account-id': true,
'role-chaining': true,
},
},
{
name: `Publish ${nameSuffix}`,
env: {
BUCKET_NAME: this.props.bucketName,
DOCS_STREAM: this.props.docsStream,
},
run: `echo "Uploading ${nameSuffix} to S3"
echo "::add-mask::$BUCKET_NAME"
S3_PATH="$DOCS_STREAM/${s3PathPrefix}$(cat dist/version.txt).zip"
LATEST="latest-${this.props.docsStream}"
# Capture both stdout and stderr
if OUTPUT=$(aws s3api put-object \\
--bucket "$BUCKET_NAME" \\
--key "$S3_PATH" \\
--body dist/${this.props.artifactPath} \\
--if-none-match "*" 2>&1); then
# File was uploaded successfully, update the latest pointer
echo "New ${nameSuffix} artifact uploaded successfully, updating latest pointer"
echo "$S3_PATH" | aws s3 cp - "s3://$BUCKET_NAME/$LATEST"
elif echo "$OUTPUT" | grep -q "PreconditionFailed"; then
# Check specifically for PreconditionFailed in the error output
echo "::warning::File already exists in S3. Skipping upload."
exit 0
else
# Any other error (permissions, etc)
echo "::error::Failed to upload ${nameSuffix} artifact"
exit 1
fi`,
},
],
});
}