Skip to content

feat(ci): Docker build rework #1

feat(ci): Docker build rework

feat(ci): Docker build rework #1

Workflow file for this run

name: 'Docker Build'
on:
push:
branches: ['main']
pull_request:
branches: ['main']
jobs:
docker-build:
name: Build & Push Docker Images
runs-on: ubuntu-latest
# We do a matrix of "docker-express", "docker-next", "docker-static", etc.
# If you have more, just add them here:
strategy:
fail-fast: false
matrix:
dockerTarget:
[
docker-express,
docker-next,
docker-static,
docker-playwright,
docker-jest,
]
steps:
# 1) Check out the code
- name: Checkout
uses: actions/checkout@v3
# 2) Set up Node (reading version from your package.json)
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: 'package.json'
# 3) Install dependencies for Nx
- name: Install dependencies
run: |
corepack enable
yarn install --frozen-lockfile
# 4) Log in to ECR using official AWS action
- name: ECR Login
uses: aws-actions/amazon-ecr-login@v2
with:
# Adjust region if needed
region: eu-west-1
# 5) Set up QEMU (for multi-arch in the future).
# Right now you only do amd64, but let's keep this so adding arm64 is easy later:
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
# If you don’t need multi-arch at all yet, you could remove this step.
image: 'public.ecr.aws/m3u4c4h9/island-is/eks-distro-build-tooling/binfmt-misc:qemu-v6.1.0'
# 6) Set up Docker Buildx so we can do buildx build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
# If you store a BuildKit image in ECR, you can specify driver-opts here.
# Otherwise, the default is fine.
install: true
# 7) Gather Nx projects that have the target in `matrix.dockerTarget`
- name: Find Nx Projects
id: nx
run: |
set -eo pipefail
# We do an Nx "affected" or just "show projects".
# For simplicity, let's just do `nx show projects --with-target=<dockerTarget>`.
PROJECTS=$(npx nx show projects --with-target=${{ matrix.dockerTarget }} | xargs)
# We'll write these projects to outputs so we can iterate in the next step.
echo "projects=$PROJECTS"
echo "projects=$PROJECTS" >> "$GITHUB_OUTPUT"
# 8) Build & push each Nx project in a loop
- name: Build and push images
run: |
# if "Find Nx Projects" found none, skip
if [ -z "${{ steps.nx.outputs.projects }}" ]; then
echo "No projects found for target='${{ matrix.dockerTarget }}'. Skipping..."
exit 0
fi
# Split the space-delimited project list
for project in ${{ steps.nx.outputs.projects }}; do
echo "------------------------"
echo "Building Docker image for project '$project'..."
echo "------------------------"
# -------------- 1) Decide on the ECR repo & tags --------------
# Typically you do ECR_REGISTRY= 821090935708.dkr.ecr.eu-west-1.amazonaws.com
# so each project is: <ECR_REGISTRY>/<project>
ECR_REGISTRY="821090935708.dkr.ecr.eu-west-1.amazonaws.com"
IMAGE_NAME="$ECR_REGISTRY/$project"
# We'll build up multiple tags. For example:
# - "sha-<shortSha>"
# - "branch-<branchName>"
# - "pr-<prNumber>"
# - "YYYYMMDD"
# - "<branchName>_<shortSha>_<runNumber>"
GIT_SHA="${GITHUB_SHA}"
SHORT_SHA="${GIT_SHA:0:10}" # first 10 chars
BRANCH_NAME="${GITHUB_REF_NAME}" # e.g. main, release-33-2-0, etc.
RUN_NUM="${GITHUB_RUN_NUMBER}"
# If it's a PR, GITHUB_REF_NAME might be "refs/pull/123/merge" or similar
# You can parse a PR number like this:
PR_NUMBER=""
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
PR_NUMBER="${{ github.event.pull_request.number }}"
fi
# Parse a date tag (YYYYMMDD):
DATE_TAG=$(date +%Y%m%d)
# If you have a "release version" in the branch name (e.g. "release-33-2-0"), you can parse it:
# For example, if BRANCH_NAME starts with "release-", we’ll grab the rest:
RELEASE_TAG=""
if [[ "$BRANCH_NAME" =~ ^release- ]]; then
RELEASE_TAG="${BRANCH_NAME#release-}" # e.g. 33-2-0
fi
# We'll collect them into a single `TAGS` arg for buildx:
# The main tag (the one you prefer to "latest" or "dev") can be first:
# Note: if you want them all to go to the same repo, you just pass multiple --tag arguments.
# Docker Buildx supports `--tag <image>:tag1 --tag <image>:tag2`
TAG_ARGS=" --tag $IMAGE_NAME:$BRANCH_NAME-$SHORT_SHA-$RUN_NUM " # e.g. main_abc1234567_1034
TAG_ARGS+=" --tag $IMAGE_NAME:sha-$SHORT_SHA " # e.g. sha-abc1234567
TAG_ARGS+=" --tag $IMAGE_NAME:date-$DATE_TAG " # e.g. date-20250109
if [ -n "$PR_NUMBER" ]; then
TAG_ARGS+=" --tag $IMAGE_NAME:pr-$PR_NUMBER "
fi
if [ -n "$RELEASE_TAG" ]; then
TAG_ARGS+=" --tag $IMAGE_NAME:release-$RELEASE_TAG "
fi
# -------------- 2) Actually build the Docker image --------------
# We'll specify a build target that corresponds to the Nx target. For example:
# docker-express => output-express
# docker-next => output-next
# ...
# Just a little case statement for clarity:
case "${{ matrix.dockerTarget }}" in
docker-express) DOCKER_TARGET="output-express" ;;
docker-next) DOCKER_TARGET="output-next" ;;
docker-static) DOCKER_TARGET="output-static" ;;
docker-playwright) DOCKER_TARGET="output-playwright" ;;
docker-jest) DOCKER_TARGET="output-jest" ;;
*)
echo "Unrecognized docker target '${{ matrix.dockerTarget }}'!"
exit 1
;;
esac
# If your Dockerfile needs certain build args (like NODE_IMAGE_TAG), add them:
# For example:
NODE_IMAGE_TAG="16-alpine"
EXTRA_ARGS="--build-arg NODE_IMAGE_TAG=$NODE_IMAGE_TAG"
EXTRA_ARGS+=" --build-arg APP=$project"
EXTRA_ARGS+=" --build-arg GIT_BRANCH=$BRANCH_NAME"
EXTRA_ARGS+=" --build-arg GIT_COMMIT_SHA=$GIT_SHA"
EXTRA_ARGS+=" --build-arg DOCKER_IMAGE_REGISTRY=$ECR_REGISTRY"
echo "Running Docker buildx build with tags:"
echo " $TAG_ARGS"
echo "And build target: $DOCKER_TARGET"
# If you want to pull a cache-from from ECR, you can do something like:
# --cache-from type=registry,ref=$IMAGE_NAME:cache-latest
# and push a cache-to for later builds. That’s beyond scope, but you’d do:
# --cache-to type=registry,ref=$IMAGE_NAME:cache-latest,mode=max
#
# If you do NOT want to rely on GitHub cache but do want your own ECR-based
# Docker layer caching, you can do it here. Or skip caching altogether.
# -------------- 3) Do the Docker buildx build + push --------------
docker buildx build \
--platform linux/amd64 \
--file scripts/ci/Dockerfile \
--target "$DOCKER_TARGET" \
$TAG_ARGS \
$EXTRA_ARGS \
--push \
.
echo "Docker image built & pushed: $IMAGE_NAME (project: $project)"
echo
done
echo "All done building for dockerTarget='${{ matrix.dockerTarget }}'."