Add Gitea Alpine registry workflow

This commit is contained in:
Joachim Schlöffel
2026-06-07 23:27:06 +02:00
parent 772eba1e20
commit bb176142e5
12 changed files with 282 additions and 14 deletions

View File

@@ -0,0 +1,48 @@
name: Build Alpine Packages
on:
push:
branches:
- master
- main
tags:
- "*"
pull_request:
workflow_dispatch:
jobs:
build-and-publish:
runs-on: ubuntu-latest
container:
image: alpine:3.23
env:
ALPINE_VERSION: "3.23"
ALPINE_ARCHES: "x86_64 aarch64"
ALPINE_REGISTRY_BRANCH: "v3.23"
ALPINE_REGISTRY_REPOSITORY: "${{ vars.PACKAGE_NAME }}"
INSTANCE_URL: "${{ vars.INSTANCE_URL }}"
PACKAGE_OWNER: "${{ vars.PACKAGE_OWNER }}"
PACKAGE_USER: "${{ secrets.PACKAGE_USER }}"
PACKAGE_TOKEN: "${{ secrets.PACKAGE_TOKEN }}"
PACKAGER: "Joachim Schlöffel <me@joachim-schloeffel.com>"
steps:
- name: Prepare Environment
run: |
apk add --no-cache --update abuild-rootbld alpine-sdk atools-apkbuild-lint bash ca-certificates curl doas git nodejs sudo tar
- name: Checkout
uses: actions/checkout@v3
- name: Build packages
run: |
scripts/apk/clean.sh
apkbuild-lint packaging/alpine/local/seaweedfs/APKBUILD
scripts/apk/ci-build.sh
scripts/apk/list-packages.sh
- name: Smoke test
run: scripts/apk/ci-smoke.sh
- name: Publish Alpine packages
if: github.event_name != 'pull_request'
run: scripts/apk/publish-gitea.sh

View File

@@ -1,6 +1,6 @@
# SeaweedFS Alpine Package
Local Alpine packaging for SeaweedFS `4.31`. The workflow runs Alpine tooling
Local Alpine 3.23 packaging for SeaweedFS `4.31`. The workflow runs Alpine tooling
inside Docker and writes signed packages under `packages/local/<arch>/`.
## Commands
@@ -17,6 +17,8 @@ mise run apk:packages
mise run apk:smoke
mise run apk:test-shell
mise run apk:publish-check
mise run apk:publish-gitea
mise run gitea-workflow-build
mise run apk:shell
mise run apk:clean
```
@@ -50,6 +52,12 @@ The package repackages upstream release tarballs, so builds use
`ALPINE_BUILD_PLATFORM=linux/amd64` by default. Signing keys and distfiles are
cached in `.cache/abuild/` and `.cache/apk-distfiles/`.
The Gitea workflow publishes to the Alpine package registry branch `v3.23`.
Override `ALPINE_VERSION` and `ALPINE_REGISTRY_BRANCH` if you intentionally
build for another Alpine branch, including `edge`.
Use `mise run gitea-workflow-build` for a local `pull_request` workflow check
through `act`; the publish step is skipped for that event.
## Test And Publish
```sh
@@ -116,6 +124,32 @@ rc-service seaweedfs.master start
If the repo key is missing on a target system, copy `.cache/abuild/*.rsa.pub`
into `/etc/apk/keys/` before `apk update`.
## Gitea Registry
The Gitea workflow reads these repository variables and secrets:
```text
Variables: INSTANCE_URL, PACKAGE_OWNER, PACKAGE_NAME
Secrets: PACKAGE_USER, PACKAGE_TOKEN
```
It uploads each built `*.apk` with HTTP `PUT` to:
```text
${INSTANCE_URL}/api/packages/${PACKAGE_OWNER}/alpine/v3.23/${PACKAGE_NAME}
```
For local publishing, run:
```sh
INSTANCE_URL=https://code.factoring.digital \
PACKAGE_OWNER=fspdigital \
PACKAGE_NAME=seaweedfs-alpine \
PACKAGE_USER=... \
PACKAGE_TOKEN=... \
mise run apk:publish-gitea
```
## Alpine Package Dos And Don'ts
Do:

View File

@@ -1,4 +1,5 @@
[tools]
act = "latest"
codex = "latest"
docker-cli = "latest"
shellcheck = "latest"
@@ -11,6 +12,10 @@ run = "scripts/apk/build.sh build"
description = "Build the Alpine package in Docker for all configured architectures"
run = "scripts/apk/build.sh build-all"
[tasks."apk:ci-build"]
description = "Build all configured Alpine packages directly in the current Alpine environment"
run = "scripts/apk/ci-build.sh"
[tasks."apk:build-x86_64"]
description = "Build the Alpine package in Docker for x86_64"
run = "scripts/apk/build.sh build x86_64"
@@ -35,6 +40,10 @@ run = "scripts/apk/build.sh lint"
description = "Install-test built packages from the local repository in Docker"
run = "scripts/apk/smoke.sh"
[tasks."apk:ci-smoke"]
description = "Install-test built packages directly in the current Alpine environment"
run = "scripts/apk/ci-smoke.sh"
[tasks."apk:test-shell"]
description = "Open an Alpine shell with the current local package build installed"
run = "scripts/apk/test-shell.sh"
@@ -47,6 +56,14 @@ run = "scripts/apk/list-packages.sh"
description = "Run lint, multi-arch build, package listing, and smoke test"
run = "scripts/apk/publish-check.sh"
[tasks."apk:publish-gitea"]
description = "Publish built packages to the Gitea Alpine package registry"
run = "scripts/apk/publish-gitea.sh"
[tasks."gitea-workflow-build"]
description = "Run the Gitea build workflow locally through act as a pull_request event"
run = "act pull_request -W .gitea/workflows/build.yml -j build-and-publish"
[tasks."apk:shell"]
description = "Open an Alpine package build shell in Docker"
run = "scripts/apk/build.sh shell"

View File

@@ -1,13 +1,13 @@
# Maintainer: Local Builder <local@example.invalid>
# Maintainer: Joachim Schlöffel <me@joachim-schloeffel.com>
pkgname=seaweedfs
pkgver=4.31
pkgrel=2
pkgrel=3
pkgdesc="Distributed storage system for object storage, file systems, and Iceberg tables"
url="https://github.com/seaweedfs/seaweedfs"
arch="x86_64 aarch64"
license="Apache-2.0"
depends="ca-certificates"
provides="!$pkgname-openrc"
depends="ca-certificates /bin/sh"
provides="!$pkgname-openrc cmd:weed=$pkgver-r$pkgrel"
install="$pkgname.pre-install"
subpackages="
$pkgname-admin-openrc:_openrc_admin:noarch
@@ -21,7 +21,7 @@ subpackages="
$pkgname-webdav-openrc:_openrc_webdav:noarch
$pkgname-worker-openrc:_openrc_worker:noarch
"
options="!check !strip"
options="!check !strip !tracedeps"
case "$CARCH" in
x86_64)

View File

@@ -1,4 +1,4 @@
ARG ALPINE_VERSION=3.22
ARG ALPINE_VERSION=3.23
FROM alpine:${ALPINE_VERSION}
ARG BUILDER_UID=1000

View File

@@ -4,9 +4,18 @@ set -euo pipefail
command_name="${1:-build}"
requested_arch="${2:-${ALPINE_ARCH:-x86_64}}"
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
alpine_version="${ALPINE_VERSION:-3.22}"
alpine_version="${ALPINE_VERSION:-3.23}"
repo_name="${ALPINE_REPO_NAME:-local}"
build_platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
builder_uid="$(id -u)"
builder_gid="$(id -g)"
if [[ "${builder_uid}" == "0" ]]; then
builder_uid=1000
fi
if [[ "${builder_gid}" == "0" ]]; then
builder_gid=1000
fi
validate_arch() {
case "$1" in
@@ -26,8 +35,8 @@ run_for_arch() {
docker build \
--platform "${build_platform}" \
--build-arg "ALPINE_VERSION=${alpine_version}" \
--build-arg "BUILDER_UID=$(id -u)" \
--build-arg "BUILDER_GID=$(id -g)" \
--build-arg "BUILDER_UID=${builder_uid}" \
--build-arg "BUILDER_GID=${builder_gid}" \
-f "${repo_root}/scripts/apk/Dockerfile" \
-t "${image_name}" \
"${repo_root}"
@@ -41,7 +50,7 @@ run_for_arch() {
-e "ALPINE_ARCH=${arch}" \
-e "CARCH=${arch}" \
-e "ALPINE_REPO_NAME=${repo_name}" \
-e "PACKAGER=${PACKAGER:-Local Builder <local@example.invalid>}" \
-e "PACKAGER=${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}" \
-v "${repo_root}:/work" \
-v "${repo_root}/.cache/abuild:/home/builder/.abuild" \
-v "${repo_root}/.cache/apk-distfiles:/var/cache/distfiles" \

55
scripts/apk/ci-build.sh Executable file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
package_dir="${APKBUILD_DIR:-${repo_root}/packaging/alpine/local/seaweedfs}"
repo_name="${ALPINE_REPO_NAME:-local}"
arches="${ALPINE_ARCHES:-x86_64 aarch64}"
packager="${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}"
if [[ "${1:-}" != "--as-builder" && "$(id -u)" == "0" ]]; then
addgroup -g 1000 builder 2>/dev/null || addgroup builder
adduser -D -u 1000 -G builder builder 2>/dev/null || true
addgroup builder abuild
addgroup builder wheel
printf 'permit nopass :wheel\n' > /etc/doas.d/wheel.conf
printf '%%wheel ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/wheel
chown -R builder:builder "${repo_root}"
exec su builder -c "ALPINE_ARCHES='${arches}' ALPINE_REPO_NAME='${repo_name}' PACKAGER='${packager}' '${BASH_SOURCE[0]}' --as-builder"
fi
export PACKAGER="${packager}"
export REPODEST="${repo_root}/packages"
export SRCDEST="${repo_root}/.cache/apk-distfiles"
git config --global --add safe.directory "${repo_root}"
mkdir -p "${repo_root}/.cache/abuild" "${SRCDEST}" "${REPODEST}" "${HOME}/.abuild"
if [[ ! -e "${HOME}/.abuild/abuild.conf" && -d "${repo_root}/.cache/abuild" ]]; then
rmdir "${HOME}/.abuild" 2>/dev/null || true
ln -s "${repo_root}/.cache/abuild" "${HOME}/.abuild"
fi
if ! compgen -G "${HOME}/.abuild/*.rsa" > /dev/null; then
abuild-keygen -a -n
fi
doas cp "${HOME}"/.abuild/*.rsa.pub /etc/apk/keys/
for arch in ${arches}; do
case "${arch}" in
x86_64|aarch64) ;;
*) printf 'unsupported Alpine architecture: %s\n' "${arch}" >&2; exit 2 ;;
esac
printf 'Building %s for %s\n' "$(basename "${package_dir}")" "${arch}"
(
export ALPINE_ARCH="${arch}"
export CARCH="${arch}"
cd "${package_dir}"
abuild -r
)
mkdir -p "${REPODEST}/${repo_name}/${arch}"
cp "${HOME}"/.abuild/*.rsa.pub "${REPODEST}/${repo_name}/${arch}/"
done

24
scripts/apk/ci-smoke.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
repo_name="${ALPINE_REPO_NAME:-local}"
arch="${ALPINE_ARCH:-$(apk --print-arch)}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc}"
repo_dir="${repo_root}/packages/${repo_name}/${arch}"
read -r -a package_list <<< "${packages}"
if [[ ! -d "${repo_dir}" ]]; then
printf 'missing local repository: packages/%s/%s\n' "${repo_name}" "${arch}" >&2
exit 1
fi
cp "${repo_dir}"/*.rsa.pub /etc/apk/keys/
echo "${repo_root}/packages/${repo_name}" >> /etc/apk/repositories
apk update
apk add "${package_list[@]}"
weed version
ls -1 /etc/seaweedfs
if ls /etc/init.d/seaweedfs.* >/dev/null 2>&1; then
find /etc/init.d -maxdepth 1 -name 'seaweedfs.*' -print | sort
fi

View File

@@ -7,7 +7,7 @@ repo_name="${ALPINE_REPO_NAME:-local}"
arch="${ALPINE_ARCH:-x86_64}"
export CARCH="${CARCH:-$arch}"
export PACKAGER="${PACKAGER:-Local Builder <local@example.invalid>}"
export PACKAGER="${PACKAGER:-Joachim Schlöffel <me@joachim-schloeffel.com>}"
if [[ -n "${PACKAGER_PRIVKEY:-}" ]]; then
export PACKAGER_PRIVKEY
fi

81
scripts/apk/publish-gitea.sh Executable file
View File

@@ -0,0 +1,81 @@
#!/usr/bin/env bash
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
repo_name="${ALPINE_REPO_NAME:-local}"
alpine_version="${ALPINE_VERSION:-3.23}"
branch="${ALPINE_REGISTRY_BRANCH:-v${alpine_version}}"
repository="${ALPINE_REGISTRY_REPOSITORY:-${PACKAGE_NAME:-main}}"
instance_url="${INSTANCE_URL:-}"
owner="${PACKAGE_OWNER:-}"
user="${PACKAGE_USER:-}"
token="${PACKAGE_TOKEN:-}"
allow_conflicts="${GITEA_APK_ALLOW_CONFLICTS:-1}"
require_env() {
local name="$1"
local value="$2"
if [[ -z "${value}" ]]; then
printf 'missing required environment variable: %s\n' "${name}" >&2
exit 2
fi
}
require_env INSTANCE_URL "${instance_url}"
require_env PACKAGE_OWNER "${owner}"
require_env PACKAGE_USER "${user}"
require_env PACKAGE_TOKEN "${token}"
instance_url="${instance_url%/}"
upload_url="${instance_url}/api/packages/${owner}/alpine/${branch}/${repository}"
package_root="${repo_root}/packages/${repo_name}"
if [[ ! -d "${package_root}" ]]; then
printf 'missing local package repository: %s\n' "${package_root}" >&2
printf 'run: mise run apk:build-all\n' >&2
exit 1
fi
shopt -s nullglob
apks=("${package_root}"/*/*.apk)
shopt -u nullglob
if [[ "${#apks[@]}" -eq 0 ]]; then
printf 'no APK files found under %s\n' "${package_root}" >&2
exit 1
fi
printf 'Publishing %d APK files to %s\n' "${#apks[@]}" "${upload_url}"
for apk in "${apks[@]}"; do
filename="$(basename "${apk}")"
status="$(
curl --silent --show-error --location \
--user "${user}:${token}" \
--upload-file "${apk}" \
--write-out '%{http_code}' \
--output /tmp/gitea-apk-publish-response \
"${upload_url}"
)"
case "${status}" in
201)
printf 'published: %s\n' "${filename}"
;;
409)
if [[ "${allow_conflicts}" == "1" ]]; then
printf 'already exists: %s\n' "${filename}"
else
printf 'conflict: %s already exists\n' "${filename}" >&2
cat /tmp/gitea-apk-publish-response >&2
exit 1
fi
;;
*)
printf 'publish failed for %s: HTTP %s\n' "${filename}" "${status}" >&2
cat /tmp/gitea-apk-publish-response >&2
exit 1
;;
esac
done

View File

@@ -2,7 +2,7 @@
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
alpine_version="${ALPINE_VERSION:-3.22}"
alpine_version="${ALPINE_VERSION:-3.23}"
platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
arch="${ALPINE_ARCH:-x86_64}"
packages="${SMOKE_PACKAGES:-seaweedfs seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc}"

View File

@@ -2,7 +2,7 @@
set -euo pipefail
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
alpine_version="${ALPINE_VERSION:-3.22}"
alpine_version="${ALPINE_VERSION:-3.23}"
platform="${ALPINE_BUILD_PLATFORM:-linux/amd64}"
arch="${ALPINE_ARCH:-x86_64}"
packages="${TEST_SHELL_PACKAGES:-seaweedfs seaweedfs-doc bash-completion seaweedfs-master-openrc seaweedfs-filer-openrc seaweedfs-worker-openrc}"