Skip to content
Merged
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
332 changes: 332 additions & 0 deletions .github/workflows/build-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
name: Reusable image build workflow with options to push to ECR or GitHub Registry
on:
workflow_call:
inputs:
artifactName:
required: false
description: If provided, downloads a previously uploaded artifact (has to be in the same workflow). Both artifactPath and artifactName have to be passed.
default: ""
type: string
artifactPath:
required: false
description: If provided, downloads a previously uploaded artifact (has to be in the same workflow). Both artifactPath and artifactName have to be passed.
default: ""
type: string
imageTargets:
required: false
description: If provided, sets targets for as many image builds as targets specified
default: ""
type: string
preScript:
required: false
description: If provided, runs a script after repo checkout and before the docker image is built. Useful in case that you need to build a package outside of the docker image (and load the artifacts via copy).
default: ""
type: string
registryHostname:
required: false
description: The hostname for the container registry
default: ghcr.io
type: string
registryOrg:
required: false
description: The registry organization
default: parcellab
type: string
registryUsername:
required: false
description: The username for the container registry
default: parcellab-dev-bot
type: string
repository_kind:
required: false
description: The kind of repository (github or ecr)
default: "github"
type: string
runner:
required: false
description: Runner type
default: ubuntu-latest
type: string
version:
required: true
type: string

env:
IMAGE_SCAN_SEVERITY: LOW
IMAGE_SCAN_SEVERITY_THRESHOLD: CRITICAL
IMAGE_SCAN_ANNOTATIONS: true
IMAGE_SCAN_TRIVY_TIMEOUT: 10m

jobs:
build-github-single:
if: inputs.repository_kind == 'github' && inputs.imageTargets == ''
environment: ${{ github.event.deployment.payload.env }}
runs-on: ${{ inputs.runner }}
steps:
- name: Checkout current git repository
uses: actions/checkout@v4
- if: inputs.preScript != ''
name: Run script before the docker image is built
run: |
echo "Run '${{ inputs.preScript }}'"
${{ inputs.preScript }}
env:
NPM_GITHUB_TOKEN: ${{ secrets.npmGithubReadToken }}
- if: inputs.artifactPath != '' && inputs.artifactName != ''
name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifactName }}
path: ${{ inputs.artifactPath }}
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ inputs.registryHostname }}
username: ${{ inputs.registryUsername }}
password: ${{ secrets.repoAccessToken }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build image
uses: docker/build-push-action@v6
with:
build-args: |
GITHUB_SHA=${{ github.sha }}
VERSION=${{ inputs.version }}
APP_NAME=${{ github.event.deployment.payload.name }}
ENVIRONMENT=${{ github.event.deployment.payload.env }}
NPM_GITHUB_TOKEN=${{ secrets.npmGithubReadToken }}
cache-from: type=registry,ref=${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}
cache-to: type=inline
context: ${{ github.event.deployment.payload.container.context }}
load: true
file: ${{ github.event.deployment.payload.container.file }}
platforms: linux/amd64
tags: |
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}:latest
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}:${{ inputs.version }}
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}:${{ github.sha }}
- name: Scan for vulnerabilities
uses: crazy-max/ghaction-container-scan@v3
with:
image: ${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}:latest
dockerfile: Containerfile
severity: ${{ env.IMAGE_SCAN_SEVERITY }}
severity_threshold: ${{ env.IMAGE_SCAN_SEVERITY_THRESHOLD }}
annotations: ${{ env.IMAGE_SCAN_ANNOTATIONS }}
env:
TRIVY_TIMEOUT: ${{ env.IMAGE_SCAN_TRIVY_TIMEOUT }}
- name: Push image to GitHub
run: |
docker push -a ${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}

build-ecr-single:
if: inputs.repository_kind == 'ecr' && inputs.imageTargets == ''
environment: ${{ github.event.deployment.payload.env }}
runs-on: ${{ inputs.runner }}
steps:
- name: Checkout current git repository
uses: actions/checkout@v4
- if: inputs.preScript != ''
name: Run script before the docker image is built
run: |
echo "Run '${{ inputs.preScript }}'"
${{ inputs.preScript }}
env:
NPM_GITHUB_TOKEN: ${{ secrets.npmGithubReadToken }}
- if: inputs.artifactPath != '' && inputs.artifactName != ''
name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifactName }}
path: ${{ inputs.artifactPath }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Configure AWS credentials
if: inputs.repository_kind == 'ecr'
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-central-1
- name: Create ECR repository if it doesn't exist
run: |
aws ecr describe-repositories --repository-names ${{ github.event.deployment.payload.name }} || \
aws ecr create-repository --repository-name ${{ github.event.deployment.payload.name }}
LIFECYCLE_POLICY='{"rules":[{"rulePriority":1,"description":"Keep last 500 images","selection":{"tagStatus":"any","countType":"imageCountMoreThan","countNumber":500},"action":{"type":"expire"}}]}'
aws ecr put-lifecycle-policy --repository-name ${{ github.event.deployment.payload.name }} --lifecycle-policy-text "$LIFECYCLE_POLICY"
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build image
uses: docker/build-push-action@v6
with:
build-args: |
GITHUB_SHA=${{ github.sha }}
VERSION=${{ inputs.version }}
APP_NAME=${{ github.event.deployment.payload.name }}
ENVIRONMENT=${{ github.event.deployment.payload.env }}
NPM_GITHUB_TOKEN=${{ secrets.npmGithubReadToken }}
cache-from: type=registry,ref=${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}
cache-to: type=inline
context: ${{ github.event.deployment.payload.container.context }}
load: true
file: ${{ github.event.deployment.payload.container.file }}
platforms: linux/amd64
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}:latest
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}:${{ inputs.version }}
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}:${{ github.sha }}
- name: Scan for vulnerabilities
if: inputs.repository_kind == 'ecr'
uses: crazy-max/ghaction-container-scan@v3
with:
image: ${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}:latest
dockerfile: Containerfile
severity: ${{ env.IMAGE_SCAN_SEVERITY }}
severity_threshold: ${{ env.IMAGE_SCAN_SEVERITY_THRESHOLD }}
annotations: ${{ env.IMAGE_SCAN_ANNOTATIONS }}
env:
TRIVY_TIMEOUT: ${{ env.IMAGE_SCAN_TRIVY_TIMEOUT }}
- name: Push image to ECR
if: inputs.repository_kind == 'ecr'
run: |
docker push -a ${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}

build-github-matrix:
if: inputs.repository_kind == 'github' && inputs.imageTargets != ''
environment: ${{ github.event.deployment.payload.env }}
runs-on: ${{ inputs.runner }}
strategy:
matrix:
containerfile_targets: ${{ fromJson(inputs.imageTargets) }}
steps:
- name: Checkout current git repository
uses: actions/checkout@v4
- if: inputs.preScript != ''
name: Run script before the docker image is built
run: |
echo "Run '${{ inputs.preScript }}'"
${{ inputs.preScript }}
env:
NPM_GITHUB_TOKEN: ${{ secrets.npmGithubReadToken }}
- if: inputs.artifactPath != '' && inputs.artifactName != ''
name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifactName }}
path: ${{ inputs.artifactPath }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ inputs.registryHostname }}
username: ${{ inputs.registryUsername }}
password: ${{ secrets.repoAccessToken }}
- name: Build ${{ matrix.containerfile_targets }} image
uses: docker/build-push-action@v6
with:
build-args: |
GITHUB_SHA=${{ github.sha }}
VERSION=${{ inputs.version }}
APP_NAME=${{ github.event.deployment.payload.name }}
ENVIRONMENT=${{ github.event.deployment.payload.env }}
NPM_GITHUB_TOKEN=${{ secrets.npmGithubReadToken }}
cache-from: type=registry,ref=${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}
cache-to: type=inline
context: ${{ github.event.deployment.payload.container.context }}
load: true
file: ${{ github.event.deployment.payload.container.file }}
platforms: linux/amd64
tags: |
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:latest
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:${{ inputs.version }}
${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:${{ github.sha }}
target: ${{ matrix.containerfile_targets }}
- name: Scan for vulnerabilities
uses: crazy-max/ghaction-container-scan@v3
with:
image: ${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:latest
dockerfile: Containerfile
severity: ${{ env.IMAGE_SCAN_SEVERITY }}
severity_threshold: ${{ env.IMAGE_SCAN_SEVERITY_THRESHOLD }}
annotations: ${{ env.IMAGE_SCAN_ANNOTATIONS }}
env:
TRIVY_TIMEOUT: ${{ env.IMAGE_SCAN_TRIVY_TIMEOUT }}
- name: Push ${{ matrix.containerfile_targets }} image to ECR
run: |
docker push -a ${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}

build-ecr-matrix:
if: inputs.repository_kind == 'ecr' && inputs.imageTargets != ''
environment: ${{ github.event.deployment.payload.env }}
runs-on: ${{ inputs.runner }}
strategy:
matrix:
containerfile_targets: ${{ fromJson(inputs.imageTargets) }}
steps:
- name: Checkout current git repository
uses: actions/checkout@v4
- if: inputs.preScript != ''
name: Run script before the docker image is built
run: |
echo "Run '${{ inputs.preScript }}'"
${{ inputs.preScript }}
env:
NPM_GITHUB_TOKEN: ${{ secrets.npmGithubReadToken }}
- if: inputs.artifactPath != '' && inputs.artifactName != ''
name: Download artifact
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifactName }}
path: ${{ inputs.artifactPath }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-central-1
- name: Create ${{ matrix.containerfile_targets }} ECR repository if it doesn't exist
run: |
aws ecr describe-repositories --repository-names ${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }} || \
aws ecr create-repository --repository-name ${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}
LIFECYCLE_POLICY='{"rules":[{"rulePriority":1,"description":"Keep last 500 images","selection":{"tagStatus":"any","countType":"imageCountMoreThan","countNumber":500},"action":{"type":"expire"}}]}'
aws ecr put-lifecycle-policy --repository-name ${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }} --lifecycle-policy-text "$LIFECYCLE_POLICY"
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build ${{ matrix.containerfile_targets }} image
uses: docker/build-push-action@v6
with:
build-args: |
GITHUB_SHA=${{ github.sha }}
VERSION=${{ inputs.version }}
APP_NAME=${{ github.event.deployment.payload.name }}
ENVIRONMENT=${{ github.event.deployment.payload.env }}
NPM_GITHUB_TOKEN=${{ secrets.npmGithubReadToken }}
cache-from: type=registry,ref=${{ inputs.registryHostname }}/${{ inputs.registryOrg }}/${{ github.event.deployment.payload.name }}
cache-to: type=inline
context: ${{ github.event.deployment.payload.container.context }}
load: true
file: ${{ github.event.deployment.payload.container.file }}
platforms: linux/amd64
tags: |
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:latest
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:${{ inputs.version }}
${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:${{ github.sha }}
target: ${{ matrix.containerfile_targets }}
- name: Scan for vulnerabilities
uses: crazy-max/ghaction-container-scan@v3
with:
image: ${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}:latest
dockerfile: Containerfile
severity: ${{ env.IMAGE_SCAN_SEVERITY }}
severity_threshold: ${{ env.IMAGE_SCAN_SEVERITY_THRESHOLD }}
annotations: ${{ env.IMAGE_SCAN_ANNOTATIONS }}
env:
TRIVY_TIMEOUT: ${{ env.IMAGE_SCAN_TRIVY_TIMEOUT }}
- name: Push ${{ matrix.containerfile_targets }} image to ECR
run: |
docker push -a ${{ steps.login-ecr.outputs.registry }}/${{ github.event.deployment.payload.name }}-${{ matrix.containerfile_targets }}
Loading
Loading