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
39 changes: 28 additions & 11 deletions .github/workflows/_build-rs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,17 @@ on:
value: ${{ jobs.build.outputs.artifact-id }}

jobs:
builder:
# Reusable workflows can't request more than their caller was granted, so
# packages: write has to be declared at every level of the chain.
permissions:
contents: read
packages: write
uses: ./.github/workflows/_builder-image.yml

build:
name: Build
needs: builder
strategy:
fail-fast: false
matrix:
Expand All @@ -45,6 +54,10 @@ jobs:
- target: ak-nss
platform: windows-2025
runs-on: ${{ matrix.platform }}
# Linux builds run inside the prebuilt builder image. ak-agent-desktop is
# the exception: it needs webkit2gtk-4.1, which bullseye doesn't have, so it
# keeps building on the runner. An empty string means "no container".
container: ${{ startsWith(matrix.platform, 'ubuntu') && matrix.target != 'ak-agent-desktop' && needs.builder.outputs.image || '' }}
env:
CARGO_TERM_COLOR: always
permissions:
Expand All @@ -65,15 +78,16 @@ jobs:
cache-dependency-path: "pnpm-lock.yaml"
# ubuntu builds run inside the builder container image, which already
# bakes in the pinned toolchain - only macos/windows need it installed
# (and cached) on the runner itself.
- if: ${{ !startsWith(matrix.platform, 'ubuntu') }}
# (and cached) on the runner itself. ak-agent-desktop is not containerised,
# so it needs the toolchain on the ubuntu runner too.
- if: ${{ !startsWith(matrix.platform, 'ubuntu') || matrix.target == 'ak-agent-desktop' }}
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with:
path: |
~/.rustup/toolchains
~/.rustup/update-hashes
key: rustup-toolchain-${{ matrix.platform }}-${{ hashFiles('rust-toolchain.toml') }}
- if: ${{ !startsWith(matrix.platform, 'ubuntu') }}
- if: ${{ !startsWith(matrix.platform, 'ubuntu') || matrix.target == 'ak-agent-desktop' }}
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1
with:
rustflags: ""
Expand All @@ -90,26 +104,27 @@ jobs:
run: |
$linkExe = (Get-Command link.exe -All | Where-Object { $_.Source -notlike '*\Git\*' } | Select-Object -First 1).Source
"CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER=$linkExe" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- if: ${{ !startsWith(matrix.platform, 'ubuntu') }}
- if: ${{ !startsWith(matrix.platform, 'ubuntu') || matrix.target == 'ak-agent-desktop' }}
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with:
path: |
~/.rustup/toolchains
~/.rustup/update-hashes
key: rustup-toolchain-${{ matrix.platform }}-${{ hashFiles('rust-toolchain.toml') }}
# /usr/local/cargo is CARGO_HOME inside the builder image; ~/.cargo is the
# runner's. Only one of the two exists per job, the other matches nothing.
- uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
/usr/local/cargo/registry
/usr/local/cargo/git
cache/
key: target-cache-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.target }}
key: target-cache-v2-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.target }}
restore-keys: |
target-cache-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-
target-cache-${{ matrix.platform }}-
- name: Build builder image
if: startsWith(matrix.platform, 'ubuntu')
run: make containers/builder/build
target-cache-v2-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-
target-cache-v2-${{ matrix.platform }}-
- run: |
make ${{ matrix.target }}/build
env:
Expand All @@ -127,5 +142,7 @@ jobs:
path: |
~/.cargo/registry
~/.cargo/git
/usr/local/cargo/registry
/usr/local/cargo/git
cache/
key: target-cache-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.target }}
key: target-cache-v2-${{ matrix.platform }}-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.target }}
68 changes: 68 additions & 0 deletions .github/workflows/_builder-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: _builder-image

# Publishes the Linux build environment to GHCR and hands the tag back to the
# caller, which uses it as the `container:` runtime for its Linux jobs.
#
# This is the ONLY place the builder image is pushed, and it is called from
# _build-rs.yml only. Everything else that needs the image (_package-linux.yml,
# test.yml) just re-derives the same tag with `make ci-container-tag` and pulls
# it - the package is public, so no credentials or packages: read are needed.
#
# The tag is a hash of the image's inputs (see containers/builder/Makefile), so
# this is a no-op on almost every run: it only builds when that exact tag is
# missing from the registry, which happens the first time a Dockerfile or
# rust-toolchain.toml change is pushed.

on:
workflow_call:
outputs:
image:
description: "Fully qualified builder image reference"
value: ${{ jobs.builder.outputs.image }}

jobs:
builder:
name: Builder image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
outputs:
image: ${{ steps.meta.outputs.tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
run: |
cd containers/builder
echo "tag<<EOF" >> $GITHUB_OUTPUT
make ci-container-tag >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- id: check
env:
IMAGE: ${{ steps.meta.outputs.tag }}
run: |
if docker manifest inspect "${IMAGE}" > /dev/null 2>&1; then
echo "${IMAGE} already published, skipping build"
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "${IMAGE} not found, building"
echo "exists=false" >> $GITHUB_OUTPUT
fi
- if: steps.check.outputs.exists != 'true'
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- if: steps.check.outputs.exists != 'true'
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- if: steps.check.outputs.exists != 'true'
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
# Repo root: the Dockerfile bind-mounts rust-toolchain.toml.
context: .
file: containers/builder/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tag }}
platforms: linux/amd64,linux/arm64
25 changes: 21 additions & 4 deletions .github/workflows/_package-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,33 @@ on:
default: '["ubuntu-24.04","ubuntu-24.04-arm"]'

jobs:
# Packaging only ever pulls the builder image - it runs after _build-rs.yml,
# which is what publishes it - so this just derives the tag from the repo
# contents rather than calling _builder-image.yml and needing packages: write.
builder:
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
image: ${{ steps.meta.outputs.tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
- id: meta
run: |
cd containers/builder
echo "tag<<EOF" >> $GITHUB_OUTPUT
make ci-container-tag >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

package:
needs: builder
strategy:
fail-fast: false
matrix:
platform: ${{ fromJSON(inputs.platforms) }}
runs-on: ${{ matrix.platform }}
# nfpm and dpkg-dev are baked into the builder image.
container: ${{ needs.builder.outputs.image }}
permissions:
contents: read
steps:
Expand Down Expand Up @@ -52,10 +73,6 @@ jobs:
with:
name: authentik_${{ matrix.platform }}_ak-pam${{ inputs.artifact_suffix }}
path: bin/
- run: |
echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list
sudo apt update
sudo apt install nfpm -y
- shell: bash
run: make vpkg/linux/package
env:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ jobs:
uses: ./.github/workflows/_build-js.yml
secrets: inherit
call-build-rs:
# packages: write for the builder image it publishes to GHCR.
permissions:
contents: read
packages: write
uses: ./.github/workflows/_build-rs.yml
secrets: inherit
call-build-ee-wcp:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ jobs:
with:
is_release: true
call-build-rs:
# packages: write for the builder image it publishes to GHCR.
permissions:
contents: read
packages: write
uses: ./.github/workflows/_build-rs.yml
secrets: inherit
with:
Expand Down
42 changes: 32 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,27 @@ permissions:
id-token: write

jobs:
# Read-only: _build-rs.yml is the only thing that publishes the builder image
# (via build_rs_e2e below, and via the build workflow). This just derives the
# same tag from the repo contents so the test jobs can pull it.
builder:
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
image: ${{ steps.meta.outputs.tag }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
- id: meta
run: |
cd containers/builder
echo "tag<<EOF" >> $GITHUB_OUTPUT
make ci-container-tag >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

test_rs:
name: Test (rust)
needs: builder
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -45,22 +64,21 @@ jobs:
- platform: macos-26
target: ak-nss
runs-on: ${{ matrix.platform }}
# Linux tests run inside the builder image, which bakes in the pinned
# toolchain, cargo-llvm-cov/nextest and the osquery toolchain.
# ak-agent-desktop needs webkit2gtk-4.1, which bullseye doesn't have, so it
# stays on the runner. An empty string means "no container".
container: ${{ startsWith(matrix.platform, 'ubuntu') && matrix.target != 'ak-agent-desktop' && needs.builder.outputs.image || '' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
- uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1
- if: ${{ !startsWith(matrix.platform, 'ubuntu') || matrix.target == 'ak-agent-desktop' }}
uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1
with:
rustflags: ""
- uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2
- if: ${{ !startsWith(matrix.platform, 'ubuntu') || matrix.target == 'ak-agent-desktop' }}
uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2
with:
tool: cargo-llvm-cov nextest
- name: Install osquery-toolchain
if: ${{ (matrix.target == 'ak-platform-facts' || matrix.target == 'ak-sysd') && (matrix.platform == 'ubuntu-24.04' || matrix.platform == 'ubuntu-24.04-arm') }}
run: |
ARCH=$(uname -m)
curl -fsSL -o /tmp/osquery-toolchain.tar.xz \
"https://github.com/osquery/osquery-toolchain/releases/download/1.3.0/osquery-toolchain-1.3.0-${ARCH}.tar.xz"
sudo tar xf /tmp/osquery-toolchain.tar.xz -C /usr/local
rm /tmp/osquery-toolchain.tar.xz
- if: ${{ (matrix.target == 'ak-platform-facts' || matrix.target == 'ak-sysd') && matrix.platform == 'windows-2025' }}
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1
- name: Force real MSVC link.exe
Expand Down Expand Up @@ -172,6 +190,10 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5
- run: make ${{ matrix.target }}/lint
build_rs_e2e:
# packages: write for the builder image it publishes to GHCR.
permissions:
contents: read
packages: write
uses: ./.github/workflows/_build-rs.yml
with:
rust_build_flags: "-C instrument-coverage -C codegen-units=1"
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ Linux DEB and RPM packages, produced via `nfpm` (invoked as a Go tool). **Linux

Requirements: Pre-built outputs from `ak-cli/build`, `sysd/build`, `ak-agent/build`, `ak-browser-support/build`, `nss/build`, and `pam/build`. Go (used to run `nfpm`). Packages produced: `authentik-cli`, `authentik-sysd`, `authentik-agent`, `libnss-authentik`, `libpam-authentik`.

#### `containers/builder/%`

Linux build environment, published to `ghcr.io/goauthentik/platform-builder`. CI uses it as the runtime for the Linux build, package and test jobs; it pins the Rust toolchain, the osquery toolchain, `nfpm` and the coverage tooling, and its Debian bullseye base is what keeps the shipped binaries' glibc requirement at 2.31.

The tag is a hash of `Dockerfile` + `rust-toolchain.toml` (`make containers/builder/ci-container-tag`), so CI only rebuilds and pushes when one of those changes.

Requirements: Docker.

#### `containers/selenium/%`

Selenium test Docker container.
Expand Down
2 changes: 1 addition & 1 deletion ak-agent-desktop/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ endif
mkdir -p "${TOP}/cache/shared"
pnpm install
pnpm run build
$(call cargo_build_local,$(TARGET),--features tauri/custom-protocol --features tauri/devtools -p ak-agent-desktop)
$(call cargo_build,$(TARGET),--features tauri/custom-protocol --features tauri/devtools -p ak-agent-desktop)
cp "${TOP}/cache/shared/release/${BIN}" "${TOP}/bin/${TARGET}/${BIND}"
ifdef SENTRY_AUTH_TOKEN
@$(call sentry_upload_symbols,"${TOP}/cache/shared/release")
Expand Down
9 changes: 4 additions & 5 deletions ak-cli/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ ifdef SENTRY_AUTH_TOKEN
@$(call sentry_upload_symbols,"${TOP}/cache/shared/release")
endif

build-local:
mkdir -p "${TOP}/bin/${TARGET}"
mkdir -p "${TOP}/cache/shared"
$(call cargo_build_local,$(TARGET))
cp "${TOP}/cache/shared/release/${BIN}" "${TOP}/bin/${TARGET}/${BIND}"
# Kept as an alias: this used to be the escape hatch from the docker-wrapped
# build, which no longer exists.
.PHONY: build-local
build-local: build

test-deploy: build
$(TME) dpkg -i /workspaces/bin/${TARGET}/authentik-${TARGET}_${VERSION}+_${ARCH}.deb
Expand Down
6 changes: 0 additions & 6 deletions ak-pam/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ endif

.PHONY: test
test:
ifeq ($(PLATFORM),gnu/linux)
ifeq ($(CI),true)
sudo apt-get update
sudo apt-get install -y libpam0g-dev libudev-dev
endif
endif
$(call cargo_test,ak-pam)

test-deploy: build
Expand Down
9 changes: 4 additions & 5 deletions ak-sysd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ ifdef SENTRY_AUTH_TOKEN
@$(call sentry_upload_symbols,"${TOP}/cache/shared/release")
endif

build-local:
mkdir -p "${TOP}/bin/${TARGET}"
mkdir -p "${TOP}/cache/shared"
$(call cargo_build_local,$(TARGET))
cp "${TOP}/cache/shared/release/${BIN}" "${TOP}/bin/${TARGET}/${BIND}"
# Kept as an alias: this used to be the escape hatch from the docker-wrapped
# build, which no longer exists.
.PHONY: build-local
build-local: build

test-deploy: build
$(TME) dpkg -i /workspaces/bin/${TARGET}/authentik-${TARGET}_${VERSION}+_${ARCH}.deb
Expand Down
Loading
Loading