Skip to content

Update and Improve the CDN Publishing Workflow#80

Open
cabutlermit wants to merge 8 commits into
mainfrom
update-cdn-publish
Open

Update and Improve the CDN Publishing Workflow#80
cabutlermit wants to merge 8 commits into
mainfrom
update-cdn-publish

Conversation

@cabutlermit

@cabutlermit cabutlermit commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Purpose and background context

Overview

  1. Update third party Actions dependencies to the latest versions.
  2. Address security concerns with the use of input values (mostly related to preventing injection attacks)
  3. Add validation steps to ensure that acceptable values are being passed to this shared workflow and fail early if there are problems
  4. Expand the capabilities of the workflow to support future repositories that might need to publish content to the CDN

The end result is a shared workflow that is backward compatible with the existing caller workflows from our "static site" repositories AND is ready to use for any future repositories that need to publish objects to paths in our CDN. It fails fast on invalid input values, has flexibility for both source paths (in the caller repository) and target paths (in the S3 bucket backing the CDN), waits until the cache invalidation is complete before finishing the workflow run, and has cleaner output to the Action summary page.

For more details about the CloudFront Distributions, see the Reference: CDN, CloudFront, Web Content document in Confluence.

Details

The actions/checkout and aws-actions/configure-aws-credentials are updated to the latest versions and their parameters are updated for clarity and security (e.g., no persisting git credentials after the initial checkout).

The whole workflow received a number of updates, from cleaning up and expanding the caller workflow inputs, to a new step to run through validation on a number of the inputs to ensure that the values are usable and if they are not, the workflow will fail fast. At the same time, the logic of the workflow was completely revamped to DRY out the code and move input & variable expansion from the run: blocks into env: blocks (this prevents injection attacks). Polling was added to the cache invalidation step to only let the workflow finish after the cache invalidation step is complete.

Knowing that this workflow will be used by future repositories to push content into the CDN, the whole concept of source & target for the aws s3 sync ... command was reworked from the old assumption that the source was always the root of the repository. Moving forward, this shared workflow expects SOURCE_PATH and TARGET_PATH input variables instead.

Finally, extra bits were added to the workflow to ensure that our existing caller workflows that still pass just the S3_URI value will still work as expected. Those caller workflows will eventually need to be updated, but for now, they will still work properly.

How can a reviewer manually see the effects of these changes?

During the development of these changes, the caller workflows from future-of-libraries-static and web-images-static were run to verify compatibility. Each of those repositories has a feature branch named test-publish-workflow that updates the dev-cdn-publish.yml workflow to point to this feature branch for the shared workflow.

A review can visit one of those two repositories, select the Actions tab, select the DEV Publish workflow, and manually run that workflow from the test-publish-workflow branch. That will call the shared workflow from this branch.

Includes new or updated dependencies?

YES: New versions of third-party Actions

Changes expectations for external applications?

NO: This is 100% backwards compatible for existing caller workflows

Code review

  • Code review best practices are documented here and you are encouraged to have a constructive dialogue with your reviewers about their preferences and expectations.

@qltysh

qltysh Bot commented Jun 1, 2026

Copy link
Copy Markdown

All good ✅

Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread .github/workflows/cdn-shared-publish.yml
Why these changes are being made:
This started as just a simple "update the version of third party
actions" and then turned into a refactor. The refactor cleans up the
logic and DRYs the code a bit and requires NO changes from any caller
workflow.

How this addresses that need:
* Update actions/checkout and aws-actions/configure-aws-credentials to
the most recent versions
* Clean up usage of environment variables in the various bash commands
throughout the workflow
* Add a "polling" step (using the `aws cloudfront wait` command) to
ensure that the cache invalidation completes before the workflow
finishes
Why these changes are being introduced:
The previous commit was a simple cleanup of the shared CDN publishing
workflow. This commit extends that work with a full refactor of the
workflow that remains compatible with our existing caller workflows
and sets the stage for future repositories that might need to publish
content to the CDN (in particular, the future work to publish the
NDE-tacos content to the CDN).

How this addresses that need:
* Create additional inputs to allow for more options for the the source
and target of the `aws s3 sync` command
* Update existing inputs with corrected "required" versus "optional"
and default values
* Update all the inputs with descriptions
* Add a "validation" step to ensure that some of the freeform inputs
are valid and fail the job quickly if they are not
* Refine the "environment" and "domain" verifications and set
environment variables with the correct combination of environment,
domain, S3 bucket name, and CloudFront domain name (this also allows
future caller workflows to not have to pass the bucket name when
calling this workflow)
* Using the new envrionment variables, simplify both the `aws s3 sync`
command and the cache invalidation command

Side effects of this change:
None

Relevant ticket(s):
* https://mitlibraries.atlassian.net/browse/NDE-96
Why these changes are being made:
Eventually, we will update the caller workflows, but for now we want
to ensure that the old caller workflows still work even with all the
changes to this shared workflow.

How these changes are implemented:
* Add a block to the validation step to parse the deprecated S3_URI
input to set "legacy" environment variables for later steps and set
a boolean to indicate if this workflow has been called by a legacy
caller workflow
* Update later steps with a conditional for the SOURCE_PATH variable
to set it correctly for legacy and non-legacy workflows

Side effects:
None.
@cabutlermit cabutlermit force-pushed the update-cdn-publish branch from adb854d to a14748c Compare June 1, 2026 14:35
Why these changes are being introduced:
First, we want to ensure that the only additional parameters supplied
by the caller workflow are `--include` and `--exclude` parameters.
Second, since we pass the parameters via an `env:` block, we have to
be extra careful with double-quotes (which are required by the
`aws s3 sync` command, but typically get stripped when expanded in a
bash script).

How these changes are implemented:
* Add a block to the validation step to throw an error if there is
any other parameter in the SYNC_PARAMS input outside of `--include` and
`--exclude`
* If the SYNC_PARAMS is valid, merge it together with the other stock
`--exclude` parameters and set one string in the GITHUB_ENV with the
full list of inclues and excludes
* Add the `eval` command to properly expand the `aws s3 sync` command
and preserve the double-quotes where they are required

Side effects:
None.
@cabutlermit cabutlermit force-pushed the update-cdn-publish branch from a14748c to 2a4e2ba Compare June 1, 2026 15:12
@cabutlermit cabutlermit marked this pull request as ready for review June 5, 2026 14:57
@cabutlermit cabutlermit requested review from a team as code owners June 5, 2026 14:57

@tim-rix tim-rix left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks OK to me

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the shared CDN publishing workflow to be safer and more flexible for both existing “static site” callers and future repositories by adding input validation, reworking sync source/target handling, and improving cache invalidation behavior.

Changes:

  • Expands workflow inputs to support SOURCE_PATH + TARGET_PATH while keeping legacy S3URI support.
  • Adds validation and refactors variable expansion toward env: to reduce injection risk and fail fast on bad inputs.
  • Updates the workflow to wait for CloudFront invalidation completion and improves Action summary output.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
README.md Updates documentation for the shared CDN publishing workflow inputs and legacy/deprecation guidance.
.github/workflows/cdn-shared-publish.yml Refactors the shared publish workflow: new inputs, validation, unified AWS credential setup, S3 sync source/target changes, and CloudFront invalidation waiting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread .github/workflows/cdn-shared-publish.yml
Why these changes are being introduced:
GitHub Copilot reviewed the pull request and noted a few issues in the
shared workflow code. After reviewing the comments by Copilot, it was
appropriate to address all of the concerns.

How this addresses that need:
* Update the Validate step to ensure that the SOURCE_PATH does not
start with `..` (preventing a directory outside of the repository
itself from being the source)
* Update the Validate step to fail quickly if there are any newline
characters in the SYNC_PARAMS input
* Update the Validate step to add validation of the value passed in to
the GHA_ROLE input to ensure that it is formmatted correctly as an
IAM Role name (using a grep filter provided by AWS)
* Update the Sync to CDN S3 Bucket step to prevent command injection;
the previous version used `eval` to handle the command and preserve
the double-quotes. The new version uses a bash array and the `read`
command to parse the VALID_SYNC_PARAMS and then just executes the
combined array (this techinque was suggested by GitHub Copilot)
* Update the Invalidate Cache step to correct the mistake in the
--paths argument (the "*" was missing previously)
* Update the README with more details on the workflow inputs and a
clearer explanation of how this shared workflow actually works

Side effects of this change:
None.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Why these changes are being introduced:=
GitHub Copilot noted additional problems that needed to be fixed; a
combination of typos in the README and mistakes in the workflow.

How this addresses that need:
* Update the validation of the GHA_ROLE using a simpler regex pattern
and the "=~" bash operator
* Rebuild the sync command, shifting the construction of the command
line parameters from the validation step to the synchronization step.
We still use a bash array to build the command, but we handle the
SYNC_PARAMS input with a combination of printf and xargs to ensure that
the input string is split correctly without any glob expansion
* Fix the typo in the cache invalidation step (the "$" was in the wrong
place)
* Update the README
@cabutlermit

Copy link
Copy Markdown
Contributor Author

@JPrevost let's try another GitHub Copilot review... 🤞

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Why these changes are being introduced:
The second review by GitHub Copilot raised a few more concerns regarding
validation steps. Those are addressed here.

How this addresses that need:
* Fix the SOURCE_PATH validation, leveraging the `realpath` bash tool
to ensure that the SOURCE_PATH does not stray outside of a subdirectory
of the repository
* Fix the "legacy check" to prevent a "custom" domain workflow for
trying to synchronize content to the root of the CDN bucket
* Minor updates to the README for clarity

Side effects of this change:
None.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

Comment thread .github/workflows/cdn-shared-publish.yml Outdated
Comment thread .github/workflows/cdn-shared-publish.yml
Comment on lines +223 to +227
echo "DISTRIBUTION_ID=$(aws ssm get-parameter \
--name "/tfvars/libraries-website/standard-cdn-id" \
--query 'Parameter.Value' \
--output text)" >> $GITHUB_ENV
echo "S3URI=s3://$BUCKET/cdn$TARGET_PATH/" >> $GITHUB_ENV
Comment thread README.md Outdated
* Address additional conerns regarding validation checks and building
the correct S3 target path. Fix the README typo.

@JPrevost JPrevost left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be easier to read and thus maintain if we split the two publication paths into separate workflows.

While both are copying files to S3, the logic diverges quite a few times to the point of this requiring a lot of cognitive load to follow even if you understand what is happening.

checkout, env setup, AWS auth would be duplicated but could be extracted into composite actions each publication workflow calls if we wanted to.

I feel like this tried to avoid duplication but in so doing increased cognitive load enough that I think making changes will be difficult to do without causing inadvertent errors as is.

I'd be happy to chat in zoom or slack about this, and if you agree but don't want to deal with that split at this time I can plod through the rest of this and get to an approval state I'm sure :)

echo "Invalid. The SOURCE_PATH must begin with a '.'"
exit 1
fi
REPO_PATH=$(realpath -e "${WORKSPACE_PATH}" 2>/dev/null)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: I'm not sure I see the value in swallowing error messages here. Was it really noisy?

Comment thread README.md
There are a number of inputs to the shared workflow, some optional and some required. Here's a summary of the inputs.

- `AWS_REGION` (**optional**, *string*, default = `us-east-1`): the region where the S3 bucket lives.
- `DOMAIN` (**optional**, *string*, default = `standard`): the default value of `standard` refers to the standard CDN. If the content in question is associated with the custom domain CDN, then the caller workflow must pass the value `custom` instead of relying on the default.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding myself wanting examples of repos using standard vs default. Not as an exhaustive permanent list, but so I could possible go look at how they are configured in the future if I wanted to set something up to work like it does. i.e. See web-images-staticfor a standard workflow andgrandchallenges-static` for custom. Note: using custom requires additional config outside this workflow (I assume)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants