-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: move build-push-ecr to Docker actions #41
base: main
Are you sure you want to change the base?
Conversation
@boringcactus thanks for taking another stab at this!
I don't see why you couldn't also make a reusable workflow for people to adopt, but I think that would be a larger change as a resuable workflow can't be used in quite the same way as an action.
I don't love it (cc @ianwestcott ) but I suppose if Amazon thinks it's okay I guess it's fine.
I'd definitely want to test it with some existing applications, especially ones that you've already called out as using some of the non-default features.
Is it possible to make using the cache optional, such that teams would need to opt-in to using it? Another approach would be to make this a non-backwards compatible update (either by releasing v3, making an action with a different name, or creating the reusable workflow). |
with: | ||
images: ${{ inputs.docker-repo }} | ||
tags: | | ||
type=sha,priority=1000,prefix=git- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: does this generate the SHA tag in the same way the old script did?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it stands, it fetches the git SHA from the GitHub Actions context, which should still be the same thing since we aren't doing anything wacky like checking out a different commit than the workflow is actually running on. If we want to handle weird edge cases like that just in case, we can pass context: git, but I don't think there's any point in that.
- uses: docker/setup-buildx-action@v3 | ||
- uses: docker/build-push-action@v5 | ||
with: | ||
load: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: you could add pull: true
to ensure that even with the cache, Docker tries to pull down updated images. I think with that, we could enable caching by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should work, yeah.
Reusable WorkflowI think the benefits of moving to a reusable workflow would only really be apparent if something in this process breaks and needs to be debugged, and migrating would be a minor nuisance in the most basic cases but somewhat more involved for our web apps that need to extract static assets from the container image to upload them to a CDN or send source maps to Sentry. Having both a reusable workflow and a composite action would involve either maintaining them both in parallel (bad) or just calling the action from the workflow (pointless). If we were starting from scratch today, I think it'd make more sense to use a reusable workflow here and then put in more standardized tooling around asset extraction (which might be helpful anyway), but the migration probably wouldn't be worth the effort. That said, Glides's existing deployment workflow involves asset extraction, so I could experiment somewhat with how difficult it actually is to build that process around a reusable Guidelines for reusable workflow vs composite action that make sense to me as of this exact moment:
If these guidelines are valid, then the existing implementation of TestingI've tested in a project that only uses the advanced tag manipulation, and that feature works properly, including the output selection based on priority. I've opened mbta/otp-deploy#29 to validate the build arg logic with multiple flags, so once that gets run, we'll be confident that that works. Unfortunately, the GitHub dependency graph feature hides private repos and forks even if I have permission to see them, so I didn't see that we have a few more repos that also pass Only a few projects use |
I'd be excited to see how that turns out! Not sure if it's a similar situation, but IIRC the primary reason Dotcom has its own bespoke setup is because, in the middle of our build-push-deploy steps, we have an extra step that extracts assets from the built image and uploads them to S3. So I'm not sure how I'd manage that with a reusable build-push-deploy action. 🤔 |
With a reusable workflow that has built-in support for extracting some files from the container, the process of migrating Glides winds up being only somewhat complicated, and the resulting UI is a lot nicer for exploring the output of each individual step than the composite action would be. Anyone who isn't handling Sentry release configuration the exact way we are would have a simpler time than that. I did change my mind about having the cache be optional - since Glides passes the Sentry release name into the container via a Docker build arg, any layer after that is useless to cache, and any layer before that is already cached because we build our container in the CI process via With a composite action, passing |
@boringcactus thanks for flagging this; I've opened #42 to address it. |
docker/build-push-action has a lot more functionality than is available in a bare
docker build
command, like caching with GitHub Actions and cleaner support for multiple tags. As such, some projects don't usembta/actions/build-push-ecr
, which means our Docker build process is fragmented. Moving this action todocker/build-push-action
should let more complexity move to the shared actions.This was also the intent of #28, which stalled out in the review process. It was a great foundation to build on - thanks a ton @thecristen! - but I've made a few additional changes:
docker-additional-args
input is just arbitrary command line flags passed todocker build
, anddocker/build-push-action
has no mechanism to provide arbitrary command line flags, since it wants to encapsulate all of the available complexity in its own inputs instead. Conveniently, however, GitHub is willing to list all the @mbta repositories that use this action, and only two of them passdocker-additional-args
(Skate and OTP-deploy), and both of those are only using--build-arg
, so with a bit of shell scripting it's possible to maintain backwards compatibility. It's not really pleasant, though, so I'd be inclined to encourage those projects to migrate to a more direct mechanism as soon as this gets released, so it can be removed promptly before anything else starts to use it.docker/metadata-action
, which I hadn't known about until readingbuild-push-ecr
refactor usingdocker/build-push-action@v3
#28, has a lot of extremely cool functionality for applying tags conditionally. Glides, which applies an extra tag to prod deploys and uses that tag in the ECS task definition, has a ton of mess that can be mostly replaced with thedocker/metadata-action
tag logic. As such, it seems like it's worth trying to allow inputs to directly passdocker/metadata-action
tag rules. The existing behavior of allowing a space-separated list indocker-additional-tags
is more widely used than the existingdocker-additional-args
behavior, though, and it would be both more annoying and less valuable to migrate that department-wide, so I think it probably makes sense to support both behaviors indefinitely.dockerfile-path
argument does not actually represent a path to a Dockerfile, but rather the path to the folder containing the Dockerfile. Since the current process is notdocker build -f ${{ inputs.dockerfile-path }}
butdocker build ${{ inputs.dockerfile-path }}
, thedockerfile-path
input is properly provided todocker/build-push-action
not asfile:
but ascontext:
. The name is misleading, but that can't be changed backwards-compatibly.aws-actions/amazon-ecr-login
instead of passing long-lived credentials to Docker directly.load: true
, and then pushes separately withdocker push --all-tags
. This is actually a really elegant solution to the fact thatdocker/build-push-action
is broken in such a way thatpush: true
andload: true
are mutually exclusive, and I wish I'd found--all-tags
in thedocker push
documentation earlier (although it may not have been there earlier).Open questions:
mbta/workflows
, but everything would have to migrate manually. (That'd save us some backwards compatibility issues, though.)aws-actions/amazon-ecr-login
appears to technically leak the AWS account ID (via the ECR registry URL) in the GitHub Actions output. (Ask me on Slack for the link that shows this.) Does that matter?mbta/actions@v2
rather than a specific minor version, but if this does wind up breaking something, it's not all that difficult to pin to@v2.2.1
or whatever until we can get it fixed.pull: true
. Do we need the ability to disable the cache? I think we're mostly pretty good about starting with immutable images in our Dockerfiles, but if anything is doingFROM alpine:latest
or what have you, it may pull from the cache before it pulls from the Docker Hub, in which case it'd always be at the old version ofalpine:latest
now that we're caching, causing this to technically be a breaking change. Several things have to go very wrong before that becomes a problem, though.