2025-04-16 18:54:36 +01:00
name : Release Docker Image
2025-04-24 17:24:28 +01:00
concurrency :
2025-04-17 14:35:16 +01:00
group : "release-image-${{ github.ref }}"
2025-04-16 18:54:36 +01:00
on :
2025-09-06 15:20:45 +01:00
pull_request :
paths-ignore :
- "*.md"
- "**/*.md"
- ".gitlab-ci.yml"
- ".gitignore"
- "renovate.json"
- "pkg/**"
- "docker/**"
- "docs/**"
2025-04-16 18:54:36 +01:00
push :
2025-09-06 15:20:45 +01:00
branches :
2025-09-06 16:21:21 +01:00
- main
2025-04-16 18:54:36 +01:00
paths-ignore :
2025-04-24 17:24:28 +01:00
- "*.md"
- "**/*.md"
- ".gitlab-ci.yml"
- ".gitignore"
- "renovate.json"
2025-09-02 12:20:23 -04:00
- "pkg/**"
2025-04-24 17:24:28 +01:00
- "docker/**"
- "docs/**"
2025-04-16 18:54:36 +01:00
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch :
env :
2025-04-24 17:24:28 +01:00
BUILTIN_REGISTRY : forgejo.ellis.link
BUILTIN_REGISTRY_ENABLED : "${{ ((vars.BUILTIN_REGISTRY_USER && secrets.BUILTIN_REGISTRY_PASSWORD) || (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false)) && 'true' || 'false' }}"
2025-04-16 18:54:36 +01:00
jobs :
define-variables :
runs-on : ubuntu-latest
outputs :
images : ${{ steps.var.outputs.images }}
images_list : ${{ steps.var.outputs.images_list }}
build_matrix : ${{ steps.var.outputs.build_matrix }}
steps :
- name : Setting variables
uses : https://github.com/actions/github-script@v7
id : var
with :
script : |
const githubRepo = '${{ github.repository }}'.toLowerCase()
const repoId = githubRepo.split('/')[1]
2025-04-24 17:24:28 +01:00
2025-04-16 18:54:36 +01:00
core.setOutput('github_repository', githubRepo)
const builtinImage = '${{ env.BUILTIN_REGISTRY }}/' + githubRepo
let images = []
if (process.env.BUILTIN_REGISTRY_ENABLED === "true") {
images.push(builtinImage)
}
core.setOutput('images', images.join("\n"))
core.setOutput('images_list', images.join(","))
const platforms = ['linux/amd64', 'linux/arm64']
core.setOutput('build_matrix', JSON.stringify({
2025-04-24 17:24:28 +01:00
platform: platforms,
2025-06-20 21:48:37 +01:00
target_cpu: ['base'],
2025-04-16 18:54:36 +01:00
include: platforms.map(platform => { return {
platform,
slug: platform.replace('/', '-')
}})
}))
build-image :
2025-04-18 14:09:09 +01:00
runs-on : dind
2025-04-16 18:54:36 +01:00
needs : define-variables
permissions :
contents : read
packages : write
attestations : write
id-token : write
strategy :
2025-04-24 17:24:28 +01:00
matrix :
{
2025-06-20 21:48:37 +01:00
"target_cpu": [ "base" ] ,
"profile": [ "release" ] ,
2025-04-24 17:24:28 +01:00
"include" :
[
{ "platform": "linux/amd64", "slug": "linux-amd64" },
{ "platform": "linux/arm64", "slug": "linux-arm64" },
] ,
"platform": [ "linux/amd64" , "linux/arm64" ] ,
}
2025-06-20 21:48:37 +01:00
2025-04-16 18:54:36 +01:00
steps :
- name : Echo strategy
run : echo '${{ toJSON(fromJSON(needs.define-variables.outputs.build_matrix)) }}'
- name : Echo matrix
run : echo '${{ toJSON(matrix) }}'
2025-05-20 22:56:51 +01:00
2025-05-01 00:47:03 +01:00
- name : Checkout repository
uses : actions/checkout@v4
with :
persist-credentials : false
2025-05-11 17:42:57 +01:00
- name : Install rust
2025-05-20 22:56:51 +01:00
id : rust-toolchain
2025-05-11 17:42:57 +01:00
uses : ./.forgejo/actions/rust-toolchain
2025-05-01 00:47:03 +01:00
2025-04-16 18:54:36 +01:00
- name : Set up Docker Buildx
uses : docker/setup-buildx-action@v3
2025-09-06 15:55:24 +01:00
with :
# Use persistent BuildKit if BUILDKIT_ENDPOINT is set (e.g. tcp://buildkit:8125)
driver : ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }}
endpoint : ${{ env.BUILDKIT_ENDPOINT || '' }}
2025-04-16 18:54:36 +01:00
- name : Set up QEMU
uses : docker/setup-qemu-action@v3
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name : Login to builtin registry
uses : docker/login-action@v3
with :
2025-04-24 17:24:28 +01:00
registry : ${{ env.BUILTIN_REGISTRY }}
username : ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
password : ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
2025-04-16 18:54:36 +01:00
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
- name : Extract metadata (labels, annotations) for Docker
id : meta
uses : docker/metadata-action@v5
with :
images : ${{needs.define-variables.outputs.images}}
# default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509
env :
DOCKER_METADATA_ANNOTATIONS_LEVELS : manifest,index
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
# It will not push images generated from a pull request
- name : Get short git commit SHA
id : sha
run : |
calculatedSha=$(git rev-parse --short ${{ github.sha }})
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
- name : Get Git commit timestamps
run : echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
2025-05-11 20:34:22 +01:00
- uses : ./.forgejo/actions/timelord
2025-04-18 22:38:17 +01:00
with :
key : timelord-v0
2025-05-11 20:34:22 +01:00
path : .
2025-05-20 22:56:51 +01:00
- name : Cache Rust registry
uses : actions/cache@v3
with :
path : |
.cargo/git
.cargo/git/checkouts
.cargo/registry
.cargo/registry/src
key : rust-registry-image-${{hashFiles('**/Cargo.lock') }}
- name : Cache cargo target
id : cache-cargo-target
uses : actions/cache@v3
with :
path : |
2025-06-20 21:48:37 +01:00
cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}
key : cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}-${{hashFiles('**/Cargo.lock') }}-${{steps.rust-toolchain.outputs.rustc_version}}
2025-05-20 22:56:51 +01:00
- name : Cache apt cache
id : cache-apt
uses : actions/cache@v3
with :
path : |
var-cache-apt-${{ matrix.slug }}
key : var-cache-apt-${{ matrix.slug }}
- name : Cache apt lib
id : cache-apt-lib
uses : actions/cache@v3
with :
path : |
var-lib-apt-${{ matrix.slug }}
key : var-lib-apt-${{ matrix.slug }}
- name : inject cache into docker
2025-08-31 00:44:28 +00:00
uses : https://github.com/reproducible-containers/buildkit-cache-dance@v3.3.0
2025-05-20 22:56:51 +01:00
with :
cache-map : |
{
".cargo/registry": "/usr/local/cargo/registry",
".cargo/git/db": "/usr/local/cargo/git/db",
2025-06-20 21:48:37 +01:00
"cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}": {
2025-05-20 22:56:51 +01:00
"target": "/app/target",
2025-06-20 21:48:37 +01:00
"id": "cargo-target-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}"
2025-05-20 22:56:51 +01:00
},
"var-cache-apt-${{ matrix.slug }}": "/var/cache/apt",
"var-lib-apt-${{ matrix.slug }}": "/var/lib/apt"
}
skip-extraction : ${{ steps.cache.outputs.cache-hit }}
2025-04-16 18:54:36 +01:00
- name : Build and push Docker image by digest
id : build
uses : docker/build-push-action@v6
with :
context : .
file : "docker/Dockerfile"
build-args : |
2025-05-01 00:38:35 +01:00
GIT_COMMIT_HASH=${{ github.sha }})
2025-06-13 14:29:14 +01:00
GIT_COMMIT_HASH_SHORT=${{ env.COMMIT_SHORT_SHA }}
2025-05-01 00:38:35 +01:00
GIT_REMOTE_URL=${{github.event.repository.html_url }}
GIT_REMOTE_COMMIT_URL=${{github.event.head_commit.url }}
2025-04-16 18:54:36 +01:00
platforms : ${{ matrix.platform }}
labels : ${{ steps.meta.outputs.labels }}
annotations : ${{ steps.meta.outputs.annotations }}
2025-04-18 21:05:17 +01:00
cache-from : type=gha
2025-05-26 19:16:50 +01:00
# cache-to: type=gha,mode=max
2025-04-16 18:54:36 +01:00
sbom : true
outputs : type=image,"name=${{ needs.define-variables.outputs.images_list }}",push-by-digest=true,name-canonical=true,push=true
env :
SOURCE_DATE_EPOCH : ${{ env.TIMESTAMP }}
# For publishing multi-platform manifests
- name : Export digest
run : |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
2025-04-24 17:24:28 +01:00
touch "/tmp/digests/${digest#sha256:}"
2025-04-16 18:54:36 +01:00
2025-07-06 22:18:51 +01:00
- name : Extract binary from container (image)
id : extract-binary-image
run : |
mkdir -p /tmp/binaries
digest="${{ steps.build.outputs.digest }}"
echo "container_id=$(docker create --platform ${{ matrix.platform }} ${{ needs.define-variables.outputs.images_list }}@$digest)" >> $GITHUB_OUTPUT
- name : Extract binary from container (copy)
run : docker cp ${{ steps.extract-binary-image.outputs.container_id }}:/sbin/conduwuit /tmp/binaries/conduwuit-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}
- name : Extract binary from container (cleanup)
run : docker rm ${{ steps.extract-binary-image.outputs.container_id }}
- name : Upload binary artifact
uses : forgejo/upload-artifact@v4
with :
name : conduwuit-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}
path : /tmp/binaries/conduwuit-${{ matrix.target_cpu }}-${{ matrix.slug }}-${{ matrix.profile }}
if-no-files-found : error
2025-04-16 18:54:36 +01:00
- name : Upload digest
2025-04-17 12:06:45 +01:00
uses : forgejo/upload-artifact@v4
2025-04-16 18:54:36 +01:00
with :
name : digests-${{ matrix.slug }}
path : /tmp/digests/*
if-no-files-found : error
2025-07-06 22:18:51 +01:00
retention-days : 5
2025-04-24 17:24:28 +01:00
2025-04-16 18:54:36 +01:00
merge :
2025-04-18 14:09:09 +01:00
runs-on : dind
2025-04-16 18:54:36 +01:00
needs : [ define-variables, build-image]
steps :
- name : Download digests
2025-04-17 12:06:45 +01:00
uses : forgejo/download-artifact@v4
2025-04-16 18:54:36 +01:00
with :
path : /tmp/digests
pattern : digests-*
merge-multiple : true
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
- name : Login to builtin registry
uses : docker/login-action@v3
with :
2025-04-24 17:24:28 +01:00
registry : ${{ env.BUILTIN_REGISTRY }}
username : ${{ vars.BUILTIN_REGISTRY_USER || github.actor }}
password : ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
2025-04-16 18:54:36 +01:00
- name : Set up Docker Buildx
uses : docker/setup-buildx-action@v3
2025-09-06 15:55:24 +01:00
with :
# Use persistent BuildKit if BUILDKIT_ENDPOINT is set (e.g. tcp://buildkit:8125)
driver : ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }}
endpoint : ${{ env.BUILDKIT_ENDPOINT || '' }}
2025-04-16 18:54:36 +01:00
- name : Extract metadata (tags) for Docker
id : meta
uses : docker/metadata-action@v5
with :
tags : |
2025-07-07 00:08:54 +01:00
type=semver,pattern={{version}},prefix=v
type=semver,pattern={{major}}.{{minor}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.0.') }},prefix=v
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }},prefix=v
2025-05-01 21:27:12 +01:00
type=ref,event=branch,prefix=${{ format('refs/heads/{0}', github.event.repository.default_branch) != github.ref && 'branch-' || '' }}
2025-04-16 18:54:36 +01:00
type=ref,event=pr
type=sha,format=long
2025-07-20 20:58:58 +01:00
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
2025-04-16 18:54:36 +01:00
images : ${{needs.define-variables.outputs.images}}
# default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509
env :
2025-04-24 17:24:28 +01:00
DOCKER_METADATA_ANNOTATIONS_LEVELS : index
2025-04-16 18:54:36 +01:00
- name : Create manifest list and push
working-directory : /tmp/digests
env :
IMAGES : ${{needs.define-variables.outputs.images}}
shell : bash
run : |
IFS=$'\n'
IMAGES_LIST=($IMAGES)
ANNOTATIONS_LIST=($DOCKER_METADATA_OUTPUT_ANNOTATIONS)
TAGS_LIST=($DOCKER_METADATA_OUTPUT_TAGS)
for REPO in "${IMAGES_LIST[@]}"; do
docker buildx imagetools create \
$(for tag in "${TAGS_LIST[@]}"; do echo "--tag"; echo "$tag"; done) \
$(for annotation in "${ANNOTATIONS_LIST[@]}"; do echo "--annotation"; echo "$annotation"; done) \
$(for reference in *; do printf "$REPO@sha256:%s\n" $reference; done)
done
- name : Inspect image
env :
IMAGES : ${{needs.define-variables.outputs.images}}
shell : bash
run : |
IMAGES_LIST=($IMAGES)
for REPO in "${IMAGES_LIST[@]}"; do
docker buildx imagetools inspect $REPO:${{ steps.meta.outputs.version }}
done