Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/actions/build-and-push-ecr-multiarch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Build & Push to ECR (Composite Action)

Builds a Docker image (Linux or Windows) and pushes it to Amazon ECR using OIDC‑assumed AWS credentials.

## Inputs

| Name | Required | Default | Description |
|------|----------|---------|-------------|
| `dockerfile` | Yes | — | Path to the Dockerfile. |
| `ecr-repo` | Yes | — | ECR repository name (e.g. `<company>/<repo>`). Must already exist. |
| `iam-role` | Yes | — | AWS IAM Role ARN assumable via GitHub OIDC. |
| `context` | No | `.` | Build context directory passed to `docker build`. |
| `image-tag` | No | (auto short SHA) | Explicit image tag; if omitted a short commit SHA is used. |
| `aws-region` | No | `eu-west-1` | AWS region for ECR. |
| `platform` | No | `linux` | `linux` or `windows`. Runner OS must match. |
| `provenance` | No | `false` | Passed to `docker/build-push-action` (Linux only). |

## Output

| Name | Description |
|------|-------------|
| `image-uri` | Fully qualified image URI (e.g. `11111111111.dkr.ecr.eu-west-1.amazonaws.com/company/repo:abc1234`). |

## Usage (Linux – default)

```yaml
name: Build Linux Image
on:
push:
branches: [ main ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: ./.github/actions/build-and-push-ecr
id: build
with:
dockerfile: <path/to/Dockerfile>
ecr-repo: <company>/<repo>
iam-role: <AWS_OIDC_ROLE_ARN> # Preferably as ${{ secrets.AWS_OIDC_ROLE_ARN }}
- name: Use image URI
run: echo "Pushed -> ${{ steps.build.outputs.image-uri }}"
```

## Usage (Windows image)

```yaml
name: Build Windows Image
on: workflow_dispatch

jobs:
build:
runs-on: windows-latest
steps:
- uses: ./.github/actions/build-and-push-ecr
id: build
with:
platform: windows
dockerfile: <path/to/Dockerfile>
ecr-repo: <company>/<repo>
iam-role: <AWS_OIDC_ROLE_ARN> # Preferably as ${{ secrets.AWS_OIDC_ROLE_ARN }}
- name: Output
shell: powershell
run: echo "Image = ${{ steps.build.outputs.image-uri }}"
```

## Notes

- The caller workflow must choose `runs-on` matching `platform`.
- Windows builds use classic `docker build`; multi-arch (linux+windows) requires separate workflows plus a manifest merge (not included).
- Ensure the ECR repository exists (create separately via IaC or AWS CLI).
- `image-tag` override is optional; omit for automatic short SHA.
- `provenance` only applies to Linux builds (silently ignored on Windows path).

## Troubleshooting

| Issue | Cause / Fix |
|-------|-------------|
| Auth failure | Check IAM role trust policy includes GitHub OIDC provider + repo. |
| Repo not found | Create ECR repo or correct `ecr-repo` name. |
| Windows build fails with base image mismatch | Ensure Dockerfile uses a Windows base matching `windows-latest` (e.g. `ltsc2022`). |
| Tag not as expected | Provide `image-tag` input explicitly. |

## Example: Custom tag

```yaml
- uses: ./.github/actions/build-and-push-ecr
with:
dockerfile: <path/to/Dockerfile>
ecr-repo: <company>/<repo>
iam-role: <AWS_OIDC_ROLE_ARN> # Preferably as ${{ secrets.AWS_OIDC_ROLE_ARN }}
image-tag: v1.4.0
```
93 changes: 93 additions & 0 deletions .github/actions/build-and-push-ecr-multiarch/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Build & Push to ECR
description: Build a Docker image (Linux or Windows) and push to AWS ECR
inputs:
dockerfile:
description: Path to Dockerfile
required: true
ecr-repo:
description: ECR repository (e.g. <company>/<repo>)
required: true
iam-role:
description: IAM Role ARN to assume via OIDC
required: true
context:
description: Build context path
required: false
default: .
image-tag:
description: Explicit image tag (defaults to short SHA)
required: false
aws-region:
description: AWS region
required: false
default: eu-west-1
platform:
description: linux or windows
required: false
default: linux
provenance:
description: Enable build provenance (linux only)
required: false
default: "false"
outputs:
image-uri:
description: Fully qualified pushed image URI
value: ${{ steps.image_uri.outputs.image_uri }}
runs:
using: composite
steps:
- name: Compute image tag (Linux)
if: ${{ inputs.platform != 'windows' }}
shell: bash
run: |
if [ -n "${{ inputs.image-tag }}" ]; then
TAG="${{ inputs.image-tag }}"
else
TAG=$(git rev-parse --short "$GITHUB_SHA")
fi
echo "IMAGE_TAG=$TAG" >> "$GITHUB_ENV"

- name: Compute image tag (Windows)
if: ${{ inputs.platform == 'windows' }}
shell: powershell
run: |
if ("${{ inputs.image-tag }}") {
$tag = "${{ inputs.image-tag }}"
} else {
$tag = (git rev-parse --short $env:GITHUB_SHA)
}
Add-Content -Path $env:GITHUB_ENV -Value "IMAGE_TAG=$tag"

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ inputs.iam-role }}
role-session-name: ecr-build-session
aws-region: ${{ inputs.aws-region }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Build & Push (Linux)
if: ${{ inputs.platform != 'windows' }}
uses: docker/build-push-action@v5
with:
context: ${{ inputs.context }}
file: ${{ inputs.dockerfile }}
push: true
provenance: ${{ inputs.provenance }}
tags: ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repo }}:${{ env.IMAGE_TAG }}

- name: Build & Push (Windows)
if: ${{ inputs.platform == 'windows' }}
shell: powershell
run: |
docker build -f "${{ inputs.dockerfile }}" -t ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repo }}:${{ env.IMAGE_TAG }} "${{ inputs.context }}"
docker push ${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repo }}:${{ env.IMAGE_TAG }}

- name: Set image URI output
id: image_uri
shell: bash
run: |
echo "image_uri=${{ steps.login-ecr.outputs.registry }}/${{ inputs.ecr-repo }}:${{ env.IMAGE_TAG }}" >> "$GITHUB_OUTPUT"