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
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ test/certs/webpki
test/certs/.softhsm-tokens
.git
.gocache
.github
137 changes: 120 additions & 17 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@ on:
- '**'

jobs:
push-release:
build-artifacts:
strategy:
fail-fast: false
matrix:
GO_VERSION:
- "1.25.0"
runs-on: ubuntu-24.04
include:
- GO_VERSION: "1.25.0"
ARCH: "amd64"
RUNNER: "ubuntu-24.04"
- GO_VERSION: "1.25.0"
ARCH: "arm64"
RUNNER: "ubuntu-24.04-arm"
runs-on: ${{ matrix.RUNNER }}
permissions:
contents: write
packages: write
outputs:
version: ${{ steps.version.outputs.version }}
go_version: ${{ matrix.GO_VERSION }}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -29,20 +37,63 @@ jobs:
- name: Verify release ancestry
run: ./tools/verify-release-ancestry.sh "$GITHUB_SHA"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Set version output
id: version
run: |
# Use commit timestamp for reproducible builds
COMMIT_TIMESTAMP="$(git show -s --format=%ct HEAD)"
VERSION="${{ matrix.GO_VERSION }}.${COMMIT_TIMESTAMP}"
echo "version=${VERSION}" >> $GITHUB_OUTPUT

- name: Build Boulder container and .deb
id: build
env:
GO_VERSION: ${{ matrix.GO_VERSION }}
DOCKER_DEFAULT_PLATFORM: linux/${{ matrix.ARCH }}
run: ./tools/container-build.sh

- name: Tag Boulder container
run: docker tag boulder "ghcr.io/letsencrypt/boulder:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
- name: Export container image for multi-platform
run: |
VERSION="${{ steps.version.outputs.version }}"
docker save "boulder:${VERSION}-${{ matrix.ARCH }}" | gzip > "boulder-image-${{ matrix.ARCH }}.tar.gz"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: boulder-${{ matrix.ARCH }}
path: |
boulder*.deb
boulder*.tar.gz
boulder-image-${{ matrix.ARCH }}.tar.gz
retention-days: 1

- name: Compute checksums
id: checksums
# The files listed on this line must be identical to the files uploaded
# in the last step.
run: sha256sum boulder*.deb boulder*.tar.gz >| boulder-${{ matrix.GO_VERSION }}.$(date +%s)-$(git rev-parse --short=8 HEAD).checksums.txt
create-release:
needs: build-artifacts
runs-on: ubuntu-24.04
permissions:
contents: write
packages: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: '0'

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/

- name: Prepare release files
run: |
# Move all .deb and .tar.gz files to current directory
find artifacts/ -name "*.deb" -o -name "*.tar.gz" | grep -v "boulder-image-" | xargs -I {} cp {} .

# Compute checksums for release files only
sha256sum boulder*.deb boulder*.tar.gz >| boulder-${{ needs.build-artifacts.outputs.version }}.$(git rev-parse --short=8 HEAD).checksums.txt

- name: Create release
env:
Expand All @@ -57,16 +108,68 @@ jobs:
# https://cli.github.com/manual/gh_release_upload
run: gh release upload "${GITHUB_REF_NAME}" boulder*.deb boulder*.tar.gz boulder*.checksums.txt

- name: Build ct-test-srv container
run: docker buildx build . --build-arg "GO_VERSION=${{ matrix.GO_VERSION }}" -f test/ct-test-srv/Dockerfile -t "ghcr.io/letsencrypt/ct-test-srv:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
push-images:
needs: build-artifacts
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Download container images
uses: actions/download-artifact@v4
with:
path: artifacts/

- name: Load and tag images
run: |
# Load architecture-specific images
docker load < artifacts/boulder-amd64/boulder-image-amd64.tar.gz
docker load < artifacts/boulder-arm64/boulder-image-arm64.tar.gz

VERSION="${{ needs.build-artifacts.outputs.version }}"
BASE_TAG="ghcr.io/${{ github.repository_owner }}/boulder:${{ github.ref_name }}-go${VERSION}"

# Tag with architecture-specific tags for manifest creation
docker tag "boulder:${VERSION}-amd64" "${BASE_TAG}-amd64"
docker tag "boulder:${VERSION}-arm64" "${BASE_TAG}-arm64"

- name: Login to ghcr.io
run: printenv GITHUB_TOKEN | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Push Boulder container
run: docker push "ghcr.io/letsencrypt/boulder:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
- name: Push architecture-specific images
run: |
VERSION="${{ needs.build-artifacts.outputs.version }}"
BASE_TAG="ghcr.io/${{ github.repository_owner }}/boulder:${{ github.ref_name }}-go${VERSION}"
docker push "${BASE_TAG}-amd64"
docker push "${BASE_TAG}-arm64"

- name: Create and push multi-platform manifest
run: |
VERSION="${{ needs.build-artifacts.outputs.version }}"
BASE_TAG="ghcr.io/${{ github.repository_owner }}/boulder:${{ github.ref_name }}-go${VERSION}"

docker buildx imagetools create -t "${BASE_TAG}" \
"${BASE_TAG}-amd64" \
"${BASE_TAG}-arm64"

- name: Push ct-test-srv container
run: docker push "ghcr.io/letsencrypt/ct-test-srv:${{ github.ref_name }}-go${{ matrix.GO_VERSION }}"
- name: Build and push ct-test-srv multi-platform
run: |
VERSION="${{ needs.build-artifacts.outputs.version }}"
docker buildx build . \
--build-arg "GO_VERSION=${{ needs.build-artifacts.outputs.go_version }}" \
-f test/ct-test-srv/Dockerfile \
--platform linux/amd64,linux/arm64 \
-t "ghcr.io/${{ github.repository_owner }}/ct-test-srv:${{ github.ref_name }}-go${VERSION}" \
--push
17 changes: 13 additions & 4 deletions .github/workflows/try-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,27 @@ jobs:
strategy:
fail-fast: false
matrix:
GO_VERSION:
- "1.25.0"
runs-on: ubuntu-24.04
include:
- GO_VERSION: "1.25.0"
ARCH: "amd64"
RUNNER: "ubuntu-24.04"
- GO_VERSION: "1.25.0"
ARCH: "arm64"
RUNNER: "ubuntu-24.04-arm"
runs-on: ${{ matrix.RUNNER }}
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Boulder container and .deb
id: build
env:
GO_VERSION: ${{ matrix.GO_VERSION }}
DOCKER_DEFAULT_PLATFORM: linux/${{ matrix.ARCH }}
run: ./tools/container-build.sh

- name: Compute checksums
Expand All @@ -47,4 +56,4 @@ jobs:
run: cat boulder*.checksums.txt

- name: Build ct-test-srv container
run: docker buildx build . --build-arg "GO_VERSION=${{ matrix.GO_VERSION }}" -f test/ct-test-srv/Dockerfile -t "ghcr.io/letsencrypt/ct-test-srv:${{ github.sha }}-go${{ matrix.GO_VERSION }}"
run: docker buildx build . --build-arg "GO_VERSION=${{ matrix.GO_VERSION }}" -f test/ct-test-srv/Dockerfile -t "ghcr.io/${{ github.repository_owner }}/ct-test-srv:${{ github.sha }}-go${{ matrix.GO_VERSION }}-${{ matrix.ARCH }}" --load
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*.a
*.so
*.pyc
boulder-*.deb
boulder-*.tar.gz

# Folders
_obj
Expand Down
21 changes: 15 additions & 6 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
# This builds Boulder in a Docker container, then creates an image
# containing just the built Boulder binaries plus some ancillary
# files that are useful for predeployment testing.
FROM docker.io/ubuntu:24.04 AS builder
# This multi-stage build first builds Boulder in a container, then
# creates a minimal image containing the built Boulder binaries and
# ancillary files for pre-deployment testing.
ARG BUILDER_BASE=docker.io/ubuntu:24.04
ARG FINAL_BASE=docker.io/ubuntu:24.04

FROM ${BUILDER_BASE} AS builder

ARG COMMIT_ID
ARG GO_VERSION
ARG VERSION
ARG TARGETPLATFORM

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get --assume-yes --no-install-recommends --update install \
ca-certificates curl gcc git gnupg2 libc6-dev

COPY tools/fetch-and-verify-go.sh /tmp
RUN /tmp/fetch-and-verify-go.sh ${GO_VERSION}
RUN case "${TARGETPLATFORM}" in \
"linux/amd64") PLATFORM="linux-amd64" ;; \
"linux/arm64") PLATFORM="linux-arm64" ;; \
*) echo "Unsupported platform: ${TARGETPLATFORM}" && exit 1 ;; \
esac && \
/tmp/fetch-and-verify-go.sh ${GO_VERSION} ${PLATFORM}
RUN tar -C /opt -xzf go.tar.gz
ENV PATH="/opt/go/bin:${PATH}"

Expand All @@ -26,7 +35,7 @@ RUN go install \
-mod=vendor \
./...

FROM docker.io/ubuntu:24.04
FROM ${FINAL_BASE}

ARG VERSION

Expand Down
59 changes: 42 additions & 17 deletions tools/container-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,61 @@

set -ex

# Without this, `go install` produces:
# # runtime/cgo
# gcc: error: unrecognized command-line option '-m64'
if [ "$(uname -m)" = "arm64" ]; then
export DOCKER_DEFAULT_PLATFORM=linux/amd64
fi

if [ -z "${GO_VERSION}" ] ; then
echo "GO_VERSION not set"
exit 1
fi

ARCH="$(uname -m)"
COMMIT_ID="$(git rev-parse --short=8 HEAD)"
VERSION="${GO_VERSION}.$(date +%s)"
# Use commit timestamp for reproducible builds
COMMIT_TIMESTAMP="$(git show -s --format=%ct HEAD)"
VERSION="${GO_VERSION}.${COMMIT_TIMESTAMP}"

# Determine what architecture to build for
if [ -n "${DOCKER_DEFAULT_PLATFORM}" ]; then
# User specified a platform override
PLATFORM="${DOCKER_DEFAULT_PLATFORM}"
else
# No override - detect from current machine
MACHINE_ARCH=$(uname -m)
case "${MACHINE_ARCH}" in
x86_64) PLATFORM="linux/amd64" ;;
aarch64) PLATFORM="linux/arm64" ;;
arm64) PLATFORM="linux/arm64" ;;
*) echo "Unsupported machine architecture: ${MACHINE_ARCH}" && exit 1 ;;
esac
fi

# Convert platform to short architecture name for file naming
case "${PLATFORM}" in
linux/amd64) ARCH="amd64" ;;
linux/arm64) ARCH="arm64" ;;
*) echo "Unsupported platform: ${PLATFORM}" && exit 1 ;;
esac

# Create platform-specific image
# Keep generic tags for standalone use
docker buildx build \
--file Containerfile \
--platform "$PLATFORM" \
--build-arg "COMMIT_ID=${COMMIT_ID}" \
--build-arg "GO_VERSION=${GO_VERSION}" \
--build-arg "VERSION=${VERSION}" \
--tag "boulder:${VERSION}-${ARCH}" \
--tag "boulder:${VERSION}" \
--tag "boulder:${COMMIT_ID}" \
--tag boulder \
--tag "boulder" \
--load \
--progress=plain \
.

docker run boulder tar -C /opt/boulder -cpz . > "./boulder-${VERSION}-${COMMIT_ID}.${ARCH}.tar.gz" .
# Produces e.g. boulder-1.25.0.1754519595-591c0545.x86_64.deb
# Create tarball
docker run "boulder" tar -C /opt/boulder -cpz . \
> "./boulder-${VERSION}-${COMMIT_ID}.${ARCH}.tar.gz"

# Create .deb package
docker run -v .:/boulderrepo \
-e "COMMIT_ID=$(git rev-parse --short=8 HEAD)" \
-e "VERSION=${VERSION}" \
boulder \
/boulderrepo/tools/make-deb.sh
-e "COMMIT_ID=${COMMIT_ID}" \
-e "VERSION=${VERSION}" \
-e "ARCH=${ARCH}" \
"boulder" \
/boulderrepo/tools/make-deb.sh
17 changes: 10 additions & 7 deletions tools/make-deb.sh
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
#!/usr/bin/env bash
#
# Produce a .deb from a built Boulder plus helper files.
# Produce a .deb package from a built Boulder container.
#
# This script expects to run on Ubuntu, as configured on GitHub Actions runners
# (with curl, make, and git installed).
# This script is executed inside the Boulder Docker container by container-build.sh.
# It packages the Boulder binary and assets into a Debian package for distribution.
#
# -e Stops execution in the instance of a command or pipeline error.
# -u Treat unset variables as an error and exit immediately.
set -eu
cd "$(realpath -- "$(dirname -- "$0")")/.."

BUILD="$(mktemp -d)"
if [ -z "${VERSION:-}" ]; then echo "VERSION not set"; exit 1; fi
if [ -z "${COMMIT_ID:-}" ]; then echo "COMMIT_ID not set"; exit 1; fi
if [ -z "${ARCH:-}" ]; then echo "ARCH not set"; exit 1; fi

BUILD="$(mktemp -d)"
mkdir -p "${BUILD}/opt"
cp -a /opt/boulder "${BUILD}/opt/boulder"

mkdir -p "${BUILD}/DEBIAN"
cat > "${BUILD}/DEBIAN/control" <<-EOF
cat >"${BUILD}/DEBIAN/control" <<-EOF
Package: boulder
Version: 1:${VERSION}
License: Mozilla Public License v2.0
Vendor: ISRG
Architecture: amd64
Architecture: ${ARCH}
Maintainer: Community
Section: default
Priority: extra
Homepage: https://github.com/letsencrypt/boulder
Description: Boulder is an ACME-compatible X.509 Certificate Authority
EOF

dpkg-deb -Zgzip -b "${BUILD}" "boulder-${VERSION}-${COMMIT_ID}.x86_64.deb"
dpkg-deb -Zgzip -b "${BUILD}" "boulder-${VERSION}-${COMMIT_ID}.${ARCH}.deb"
Loading