Skip to content
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

CI/CD: publish docker image in GHCR #322

Merged
merged 12 commits into from
Aug 10, 2023
6 changes: 3 additions & 3 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ runs:

- name: Determine artifact output filename
id: artifact-name-generator
run: echo "artifact-name=irma-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.os == 'windows' && '.exe' || '' }}" >> $GITHUB_OUTPUT
run: echo "artifact-name=irma-${{ inputs.os }}-${{ inputs.arch }}${{ inputs.os == 'windows' && '.exe' || '' }}" >> $GITHUB_OUTPUT
shell: bash

- name: Build
run: go build -v -a -ldflags '-extldflags "-static"' -o ${{ steps.artifact-name-generator.outputs.artifact-name }} ./irma
shell: bash
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
GOOS: ${{ inputs.os }}
GOARCH: ${{ inputs.arch }}
CGO_ENABLED: "0"
92 changes: 78 additions & 14 deletions .github/workflows/delivery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@ name: Delivery

on:
push:
tags: [ v* ]
branches: [ master ]
release:
# Note: a current limitation is that when a release is edited after publication, then the Docker tags are not automatically updated.
types: [ published ]

permissions:
contents: write
packages: write

# Disable concurrency to prevent that images are tagged in the wrong order.
concurrency:
group: delivery

jobs:

ensure-release-present:
prepare:
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
is-head-master: ${{ steps.is-head-master.outcome == 'success' }}
is-latest-release: ${{ steps.is-latest-release.outcome == 'success' }}
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -23,30 +32,76 @@ jobs:
run: git branch --contains ${{ github.sha }} | grep -x "* master"
shell: bash

- name: Check whether this event is the HEAD of master
continue-on-error: true
id: is-head-master
run: git rev-parse HEAD | grep -x ${{ github.sha }}
shell: bash

- uses: actions/checkout@v3

- name: Check whether version.go contains the new version number
if: github.event_name == 'release'
run: cat version.go | grep ${GITHUB_REF_NAME:1}
shell: bash

- name: Check whether CHANGELOG.md contains the new version number
if: github.event_name == 'release'
run: cat CHANGELOG.md | grep "\[${GITHUB_REF_NAME:1}\]"
shell: bash

- name: Check whether release is present
id: release-present
run: gh release view ${{ github.ref_name }}
- name: Check whether the release is latest
continue-on-error: true
id: is-latest-release
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release view --json tagName --jq .tagName | grep -x ${{ github.event.release.tag_name }}
shell: bash

build-docker-image:
runs-on: ubuntu-latest
needs: prepare
steps:
- uses: actions/checkout@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build Docker image
run: docker build -t ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} .

- name: Tag Docker image (edge)
if: needs.prepare.outputs.is-head-master == 'true'
run: docker tag ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} ghcr.io/${{ github.repository_owner }}/irma:edge

- name: Tag Docker image (version)
if: github.event_name == 'release'
run: docker tag ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} ghcr.io/${{ github.repository_owner }}/irma:${{ github.event.release.tag_name }}

- name: Tag Docker image (latest)
if: needs.prepare.outputs.is-latest-release == 'true'
run: docker tag ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} ghcr.io/${{ github.repository_owner }}/irma:latest

- name: Make new release if necessary
if: steps.release-present.outcome == 'failure'
run: gh release create ${{ github.ref_name }} -t "${{ github.ref_name }}" -n "Check CHANGELOG.md in repository."
- name: Push Docker image (edge)
if: needs.prepare.outputs.is-head-master == 'true'
run: docker push ghcr.io/${{ github.repository_owner }}/irma:edge

- name: Push Docker image (version)
if: github.event_name == 'release'
run: docker push ghcr.io/${{ github.repository_owner }}/irma:${{ github.event.release.tag_name }}

- name: Tag Docker image (latest)
if: needs.prepare.outputs.is-latest-release == 'true'
run: docker push ghcr.io/${{ github.repository_owner }}/irma:latest

build-release-artifact:
needs: ensure-release-present
needs: prepare
runs-on: ubuntu-latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix:
os: [ linux, darwin, windows ]
Expand All @@ -67,4 +122,13 @@ jobs:
arch: ${{ matrix.arch }}

- name: Upload artifact
run: gh release upload ${{ github.ref_name }} ${{ steps.build.outputs.artifact-name }}
uses: actions/upload-artifact@v3
with:
name: irma-${{ matrix.os }}-${{ matrix.arch }}
path: ${{ steps.build.outputs.artifact-name }}

- name: Upload artifact to release
if: github.event_name == 'release'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload ${{ github.event.release.tag_name }} ${{ steps.build.outputs.artifact-name }}
33 changes: 9 additions & 24 deletions .github/workflows/status-checks-dockerfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,24 @@
name: Status checks (Dockerfile)

on:
push:
branches: [ master ]
paths:
- Dockerfile
# Delivery pipeline already runs this on push to master.
pull_request:
paths:
- Dockerfile
schedule:
# Run every monday on 9:00 in the morning (UTC).
- cron: "0 9 * * 1"
# Make it possible to trigger the checks manually.
workflow_dispatch:

# Building the Dockerfile includes downloading the IRMA schemes.
# Therefore, we only run one check at the time, and we put a limit on the event types triggering this job.
concurrency:
group: dockerfile

jobs:
# Building the Dockerfile includes downloading the IRMA schemes.
# Therefore, we only run one check at the time, and we put a limit on the event types triggering this job.
docker-build-all:
docker-build:
runs-on: ubuntu-latest
strategy:
max-parallel: 1
matrix:
# busybox is not working yet.
image:
- "debian:stable"
- "alpine:latest"
- "ubuntu:latest"
- "centos:latest"
- "amazonlinux:latest"
steps:
- uses: actions/checkout@v3

- name: Build Dockerfile
run: docker build -t privacybydesign/irma:edge --build-arg BASE_IMAGE=${{ matrix.image }} .
run: docker build -t ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} .

- name: Test Docker image
run: docker run privacybydesign/irma:edge version
run: docker run ghcr.io/${{ github.repository_owner }}/irma:${{ github.sha }} version
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- E-mail address revalidation, addressing issues where user's e-mail addresses can be (temporary) invalid
- Publish the Docker image of the `irma`` CLI tool on ghcr.io/privacybydesign/irma
bobhageman marked this conversation as resolved.
Show resolved Hide resolved

### Changed
- Use separate application user in Dockerfile for entrypoint
- Rename RevocationStorage's UpdateLatest function to LatestUpdates. This name better fits its behaviour. The functionality stays the same.
- Validate revocation witness before revocation update is applied
- RevocationStorage's EnableRevocation function does not return an error anymore if it has been enabled already
- Use a scratch Docker image as base for the Dockerfile
bobhageman marked this conversation as resolved.
Show resolved Hide resolved
- Custom WrapErrorPrefix function that respects the error's type
- Log info message of irma.SessionError errors

Expand Down
31 changes: 16 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# Use variable base image, such that we can also build for other base images, like alpine.
ARG BASE_IMAGE=debian:stable-slim

FROM golang:1 as build
FROM golang:1-alpine as build

# Set build environment
ENV CGO_ENABLED=0
Expand All @@ -11,23 +8,27 @@ COPY . /irmago
WORKDIR /irmago
RUN go build -a -ldflags '-extldflags "-static"' -o "/bin/irma" ./irma

FROM $BASE_IMAGE
# Create application user
RUN adduser -D -u 1000 -g irma irma

# The amazonlinux image does not include adduser, so we have to install this first.
RUN if grep -q -E 'Amazon Linux' /etc/os-release; then yum install -y shadow-utils; fi
# Start building the final image
FROM scratch

# Add application user
RUN adduser --disabled-password --gecos '' irma || adduser irma
# Copy binary from build stage
COPY --from=build /bin/irma /bin/irma

# The debian image does not include ca-certificates, so we have to install this first.
RUN if which apt-get &> /dev/null; then apt-get update && apt-get install -y ca-certificates; fi
# Add TLS root certificates
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

COPY --from=build /bin/irma /usr/local/bin/irma
# Ensure the application user and group is set
COPY --from=build /etc/passwd /etc/passwd
COPY --from=build /etc/group /etc/group
COPY --from=build --chown=irma:irma /home/irma/ /home/irma/

# Switch to application user
USER irma

# Include schemes in the Docker image to speed up the start-up time.
RUN irma scheme download
# Include schemes in the Docker image to speed up the start-up time
RUN ["/bin/irma", "scheme", "download"]

ENTRYPOINT ["irma"]
ENTRYPOINT ["/bin/irma"]
34 changes: 21 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

Technical documentation of all components of `irmago` and more can be found at https://irma.app/docs.

## Running
## Running (development)

The easiest way to run the `irma` command line tool is using Docker.
The easiest way to run the `irma` command line tool for development purposes is using Docker.

docker-compose run irma

Expand All @@ -30,30 +30,38 @@ You can run the `irma keyshare` services locally using the test configuration in
docker-compose run -p 8081:8081 irma keyshare myirmaserver -c ./testdata/configurations/myirmaserver.yml

## Installing
### Using Go
To install the latest released version of the `irma` command line tool using Go, you do the following.

git clone https://github.com/privacybydesign/irmago
go install github.com/privacybydesign/irmago/irma@latest

`irmago` and its subpackages use Go modules for their dependencies. The `go` command will automatically download dependencies when needed.
You can also specify an exact version. You should replace `v0.0.0` with the desired version number.

go install github.com/privacybydesign/irmago/[email protected]

To install the `irma` command line tool:
### Using a container
If you want a container image of the `irma` command line tool, then you can use our `ghcr.io/privacybydesign/irma` image.

go install ./irma
docker run ghcr.io/privacybydesign/irma:latest

You can also include the `irma` command line tool in a Docker image, using a base image of your choice. The default base image is Debian's `stable-slim`.
The images are tagged in the following way:
- `latest`: latest released version of `irma`
- `edge`: HEAD of the main development branch (`master`)
- `v0.0.0`: `irma` version (replace `v0.0.0` with the desired version number)

docker build --build-arg BASE_IMAGE=alpine -t privacybydesign/irma:edge .
When you build for production, we recommend you to use the [latest release](https://github.com/privacybydesign/irmago/releases/latest).

When you build for production, we recommend you to build the [latest release](https://github.com/privacybydesign/irmago/releases/latest). You should replace `v0.0.0` with the latest version number.

docker build -t privacybydesign/irma https://github.com/privacybydesign/irmago.git#v0.0.0

In case you want to build `v0.8.0` or lower, then you should do some extra steps. The `Dockerfile` was not part of the repository at that time.
In case you want to use `v0.12.6` or lower, then you should build it yourself.

VERSION=v0.8.0
git checkout $VERSION
git checkout master -- Dockerfile
docker build -t privacybydesign/irma:$VERSION .

### Using pre-compiled binaries
You can find pre-compiled binaries of the `irma` command line tool on the [GitHub release page](https://github.com/privacybydesign/irmago/releases).
We recommend you to use the [latest release](https://github.com/privacybydesign/irmago/releases/latest).

## Running the unit tests

Some of the unit tests connect to locally running external services, namely PostgreSQL and an SMTP server running at port 1025. These need to be up and running before these tests can be executed. This can either be done using `docker-compose` or by following the instructions below to install the services manually.
Expand Down