Skip to content

Rust CI/CD

Rust CI/CD #4

Workflow file for this run

# A common workflow for building, testing and publishing docker images in the samply organization (see https://github.com/samply).
# Upon completion of this workflow, following actions will be taken:
# 1) Build the docker image using a Dockerfile in the source code (default is ./Dockerfile)
# 2) Scan the image for vulnerabilities with trivy (see https://github.com/aquasecurity/trivy)
# 3) Upload the scan results from step 2 to the github security tab of the repository
# 4) Generating appropriate image tags for publishing using the docker/metadata-action. Following Rules are applied:
# 1. Running the action on push to the main branch will trigger tagging image as latest
# 2. Running the action on push to a git branch trigger tagging image as "<branchname>"
# 3. Running the action on push of a git tag matching the semver schema will trigger tagging image with {MAJOR}, {MAJOR}.{MINOR} and {MAJOR}.{MINOR}.{PATCH}
# 4. Running the action on push to a pull request, will trigger tagging for the github container registry with ghcr.io/<repository-name>/<pr-reference>. This will be skipped for private repositories.
# 5. Running the action on a scheduled basis will trigger tagging images with "nightly".
# 5) Rebuild the image for all necessary platforms an publish it based on the applied tags from 4.
#
# An usage example for this action is provided in the samply organization: https://github.com/samply/.github/blob/main/workflow-templates/docker-ci-template.yml
name: Build, Test and Deploy Docker Image
on:
workflow_call:
inputs:
# The Docker Hub Repository you want eventually push to, e.g samply/share-client
image-name:
required: true
type: string
# Define special prefixes for docker tags
image-tag-prefix:
required: false
type: string
# Define special suffixes for docker tags
image-tag-suffix:
required: false
type: string
# Define the build context of your image, typically default '.' will be enough
build-context:
required: false
type: string
default: '.'
# Define the Dockerfile of your image, typically default './Dockerfile' will be enough
build-file:
required: false
type: string
default: './Dockerfile'
build-platforms:
required: false
type: string
default: "linux/amd64,linux/arm64/v8"
build-platforms-short:
required: false
type: string
# A list of build arguments, passed to the docker build
# FIXME: GitHub Actions currently doesn't support list types on inputs. This needs to be parsed by us from string.
build-args:
required: false
type: string
# If your actions generate an artifact in a previous build step, you can tell this worflow to download it.
# '*' will download *ALL* build artifacts into named subdirectories.
artifact-name:
required: false
type: string
default: ''
binary-name:
required: false
type: string
# Set to none, dockerhub, ghcr or both
push-to:
required: true
type: string
secrets:
DOCKERHUB_USERNAME:
required: true
DOCKERHUB_TOKEN:
required: true
jobs:
tidy-ghcr:
name: Tidy GHCR
runs-on: ubuntu-latest
steps:
- name: Tidy GHCR
- uses: actions/delete-package-versions@v5
with:
package-name: ${{ inputs.image-name }}
package-type: 'container'
min-versions-to-keep: 10
build:
name: Dockerize${{ inputs.binary-name && format(' ({0})', inputs.binary-name) }}${{ inputs.image-tag-suffix && format(' ({0})', inputs.image-tag-suffix) }}
runs-on: ubuntu-latest
steps:
- name: Read vars
env:
ARCHS_LONG: ${{ inputs.build-platforms }}
ARCHS_SHORT: ${{ inputs.build-platforms-short }}
PUSH_TO: ${{ inputs.push-to }}
run: |
RESULT=""
if [ "$ARCHS_SHORT" == "" ]; then
RESULT="$ARCHS_LONG"
else
for ARCH in $(echo "$ARCHS_SHORT" | jq -r '.[]'); do
if [ "$ARCH" == "amd64" ]; then
RESULT="$RESULT,linux/amd64"
fi
if [ "$ARCH" == "arm64" ]; then
RESULT="$RESULT,linux/arm64/v8"
fi
done
fi
GHCR=
DOCKERHUB=
case "$PUSH_TO" in
both)
GHCR=true
DOCKERHUB=true
;;
dockerhub)
DOCKERHUB=true
;;
ghcr)
GHCR=true
;;
none)
;;
*)
echo "Unsupported push target: \"$PUSH_TO\". Please supply none, dockerhub, ghcr or both."
exit 1
esac
echo "Resulting build_platforms is \"$RESULT\""
echo "build_platforms=$RESULT" >> $GITHUB_ENV
echo "dockerhub=$DOCKERHUB" >> $GITHUB_ENV
echo "ghcr=$GHCR" >> $GITHUB_ENV
- name: Analyze repository
run: |
VISIBILITY="$(curl https://api.github.com/repos/${{ github.repository }} | jq -r .visibility)"
if [ "$VISIBILITY" != "public" ]; then
echo "Repository is not public -- will skip security scans and push to github container registry."
echo "security-scan=false" >> $GITHUB_ENV
else
echo "security-scan=true" >> $GITHUB_ENV
fi
- name: Checkout Source Code
uses: actions/checkout@v2
- name: Download specific Build Artifact to artifacts/
if: ${{ inputs.artifact-name != '' && inputs.artifact-name != '*' }}
uses: actions/download-artifact@v3
with:
name: ${{ inputs.artifact-name }}
path: artifacts
- name: Download all Build Artifacts to artifacts/
if: ${{ inputs.artifact-name == '*' }}
uses: actions/download-artifact@v3
with:
path: artifacts
- name: Replace binary name in Dockerfile
if: ${{ inputs.binary-name }}
env:
BUILD_FILE: ${{ inputs.build-file }}
BINARY_NAME: ${{ inputs.binary-name }}
run: |
sed -i "s,/usr/local/bin/samply,/usr/local/bin/${BINARY_NAME},g" ${BUILD_FILE}
- name: ls
run: ls -laR
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and Export to Docker
uses: docker/build-push-action@v2
with:
context: ${{ inputs.build-context }}
file: ${{ inputs.build-file }}
build-args: ${{ inputs.build-args }}
# NOTE: Not specifying build platforms here due to conflict with the load option!
load: true
tags: ${{ inputs.image-name }}
- name: Run Trivy Vulnerability Scanner
uses: aquasecurity/trivy-action@master
if: ${{ env.security-scan != 'false' }}
with:
image-ref: ${{ inputs.image-name }}
format: sarif
timeout: '10m0s'
ignore-unfixed: true
output: trivy-results.sarif
- name: Upload Trivy Scan Results to GitHub Security Tab
uses: github/codeql-action/upload-sarif@codeql-bundle-20211208
if: ${{ env.security-scan != 'false' }}
with:
sarif_file: trivy-results.sarif
- name: Define Image Tags for Github Container Registry
id: docker-meta-ghcr
if: env.ghcr
uses: docker/metadata-action@v3
with:
images: |
"ghcr.io/${{ inputs.image-name }}"
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr,prefix=${{ inputs.image-tag-prefix }},suffix=${{ inputs.image-tag-suffix }}pr-
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,format=long,prefix=${{ inputs.image-tag-prefix }},suffix=${{ inputs.image-tag-suffix }}sha-
# set latest tag for default branch
type=raw,value=latest,enable={{is_default_branch}}
flavor: |
prefix=${{ inputs.image-tag-prefix }},onlatest=true
suffix=${{ inputs.image-tag-suffix }},onlatest=true
- name: Login to Github Container Registry
if: env.ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and Push Image to Github Container Registry
if: env.ghcr
uses: docker/build-push-action@v2
with:
context: ${{ inputs.build-context }}
file: ${{ inputs.build-file }}
push: true
platforms: ${{ env.build_platforms }}
build-args: ${{ inputs.build-args }}
labels: ${{ steps.docker-meta-ghcr.outputs.labels }}
tags: ${{ steps.docker-meta-ghcr.outputs.tags }}
- name: Generate Image Tags for Docker Hub
id: docker-meta
uses: docker/metadata-action@v3
if: env.dockerhub
with:
images: |
${{ inputs.image-name }}
tags: |
type=schedule
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
# set latest tag for default branch
type=raw,value=latest,enable={{is_default_branch}}
flavor: |
prefix=${{ inputs.image-tag-prefix }},onlatest=true
suffix=${{ inputs.image-tag-suffix }},onlatest=true
- name: Login to Docker Hub
uses: docker/login-action@v1
if: env.dockerhub
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Image to Docker Hub
uses: docker/build-push-action@v2
if: env.dockerhub
with:
context: ${{ inputs.build-context }}
file: ${{ inputs.build-file }}
push: true
platforms: ${{ env.build_platforms }}
build-args: ${{ inputs.build-args }}
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}