Add Forgejo namespace release workflow
This commit is contained in:
parent
9e3e8fa783
commit
b15b6624cb
4 changed files with 302 additions and 0 deletions
60
.forgejo/workflows/release.yml
Normal file
60
.forgejo/workflows/release.yml
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
name: Release Build
|
||||||
|
runs-on: namespace-profile-linux-medium
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ github.token }}
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Bootstrap Nix
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
chmod +x Scripts/ci/ensure-nix.sh
|
||||||
|
Scripts/ci/ensure-nix.sh
|
||||||
|
|
||||||
|
- name: Build release artifacts
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
RELEASE_REF: ${{ github.ref_name }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
ref="${RELEASE_REF:-manual-${GITHUB_SHA::7}}"
|
||||||
|
export RELEASE_REF="${ref}"
|
||||||
|
chmod +x Scripts/ci/build-release-artifacts.sh
|
||||||
|
nix develop .#ci -c Scripts/ci/build-release-artifacts.sh
|
||||||
|
|
||||||
|
- name: Upload release artifacts
|
||||||
|
uses: https://code.forgejo.org/actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: burrow-release-${{ github.ref_name }}
|
||||||
|
path: dist/*
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
- name: Publish Forgejo release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
RELEASE_TAG: ${{ github.ref_name }}
|
||||||
|
API_URL: ${{ github.api_url }}
|
||||||
|
REPOSITORY: ${{ github.repository }}
|
||||||
|
TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
chmod +x Scripts/ci/publish-forgejo-release.sh
|
||||||
|
nix develop .#ci -c Scripts/ci/publish-forgejo-release.sh
|
||||||
20
Scripts/ci/build-release-artifacts.sh
Executable file
20
Scripts/ci/build-release-artifacts.sh
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
cd "${repo_root}"
|
||||||
|
|
||||||
|
release_ref="${RELEASE_REF:-manual-${GITHUB_SHA:-unknown}}"
|
||||||
|
target="x86_64-unknown-linux-gnu"
|
||||||
|
out_dir="${repo_root}/dist"
|
||||||
|
staging="${out_dir}/burrow-${release_ref}-${target}"
|
||||||
|
|
||||||
|
mkdir -p "${staging}"
|
||||||
|
|
||||||
|
cargo build --locked --release -p burrow --bin burrow
|
||||||
|
install -m 0755 target/release/burrow "${staging}/burrow"
|
||||||
|
cp README.md "${staging}/README.md"
|
||||||
|
|
||||||
|
tarball="${out_dir}/burrow-${release_ref}-${target}.tar.gz"
|
||||||
|
tar -C "${out_dir}" -czf "${tarball}" "$(basename "${staging}")"
|
||||||
|
shasum -a 256 "${tarball}" > "${tarball}.sha256"
|
||||||
157
Scripts/ci/ensure-nix.sh
Executable file
157
Scripts/ci/ensure-nix.sh
Executable file
|
|
@ -0,0 +1,157 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source_nix_profile() {
|
||||||
|
local candidate
|
||||||
|
for candidate in \
|
||||||
|
"/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh" \
|
||||||
|
"${HOME}/.nix-profile/etc/profile.d/nix.sh"
|
||||||
|
do
|
||||||
|
if [[ -f "${candidate}" ]]; then
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${candidate}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
linux_cp_supports_preserve() {
|
||||||
|
cp --help 2>&1 | grep -q -- '--preserve'
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_root_owned_home() {
|
||||||
|
if [[ "$(id -u)" -ne 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "${HOME}" ]] || [[ ! -O "${HOME}" ]]; then
|
||||||
|
export HOME="/root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${HOME}"
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_linux_nixbld_accounts() {
|
||||||
|
if [[ "$(id -u)" -ne 0 ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v getent >/dev/null 2>&1 && getent group nixbld >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v addgroup >/dev/null 2>&1 && ! command -v groupadd >/dev/null 2>&1; then
|
||||||
|
addgroup -S nixbld >/dev/null 2>&1 || true
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
adduser -S -D -H -h /var/empty -s /sbin/nologin -G nixbld "nixbld${i}" >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v groupadd >/dev/null 2>&1; then
|
||||||
|
groupadd -r nixbld >/dev/null 2>&1 || true
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
useradd \
|
||||||
|
--system \
|
||||||
|
--no-create-home \
|
||||||
|
--home-dir /var/empty \
|
||||||
|
--shell /usr/sbin/nologin \
|
||||||
|
--gid nixbld \
|
||||||
|
"nixbld${i}" >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "linux nix bootstrap requires nixbld group creation support" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_linux_nix_bootstrap_prereqs() {
|
||||||
|
if linux_cp_supports_preserve; then
|
||||||
|
ensure_root_owned_home
|
||||||
|
ensure_linux_nixbld_accounts
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v apk >/dev/null 2>&1; then
|
||||||
|
apk add --no-cache coreutils xz >/dev/null
|
||||||
|
elif command -v apt-get >/dev/null 2>&1; then
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -y >/dev/null
|
||||||
|
apt-get install -y coreutils xz-utils >/dev/null
|
||||||
|
elif command -v dnf >/dev/null 2>&1; then
|
||||||
|
dnf install -y coreutils xz >/dev/null
|
||||||
|
elif command -v yum >/dev/null 2>&1; then
|
||||||
|
yum install -y coreutils xz >/dev/null
|
||||||
|
else
|
||||||
|
echo "linux nix bootstrap requires GNU cp but no supported package manager was found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
linux_cp_supports_preserve || {
|
||||||
|
echo "linux nix bootstrap still lacks GNU cp after installing prerequisites" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_root_owned_home
|
||||||
|
ensure_linux_nixbld_accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! command -v nix >/dev/null 2>&1; then
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "curl is required to install nix" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Linux)
|
||||||
|
ensure_linux_nix_bootstrap_prereqs
|
||||||
|
curl -fsSL https://nixos.org/nix/install | sh -s -- --no-daemon
|
||||||
|
;;
|
||||||
|
Darwin)
|
||||||
|
installer="$(mktemp -t burrow-nix.XXXXXX)"
|
||||||
|
trap 'rm -f "${installer}"' EXIT
|
||||||
|
curl -fsSL -o "${installer}" https://install.determinate.systems/nix
|
||||||
|
chmod +x "${installer}"
|
||||||
|
if command -v sudo >/dev/null 2>&1; then
|
||||||
|
if sudo -n true 2>/dev/null; then
|
||||||
|
sudo -n sh "${installer}" install --no-confirm
|
||||||
|
else
|
||||||
|
sudo sh "${installer}" install --no-confirm
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
sh "${installer}" install --no-confirm
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unsupported platform for nix bootstrap: $(uname -s)" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
source_nix_profile || true
|
||||||
|
export PATH="${HOME}/.nix-profile/bin:/nix/var/nix/profiles/default/bin:/nix/var/nix/profiles/default/sbin:${PATH}"
|
||||||
|
|
||||||
|
config_root="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||||
|
config_file="${config_root}/nix/nix.conf"
|
||||||
|
if [[ -e "${config_file}" && ! -w "${config_file}" ]]; then
|
||||||
|
config_root="$(mktemp -d -t burrow-nix-config.XXXXXX)"
|
||||||
|
export XDG_CONFIG_HOME="${config_root}"
|
||||||
|
config_file="${XDG_CONFIG_HOME}/nix/nix.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname -- "${config_file}")"
|
||||||
|
cat > "${config_file}" <<'EOF'
|
||||||
|
experimental-features = nix-command flakes
|
||||||
|
sandbox = true
|
||||||
|
fallback = true
|
||||||
|
substituters = https://cache.nixos.org
|
||||||
|
trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
|
||||||
|
EOF
|
||||||
|
|
||||||
|
command -v nix >/dev/null 2>&1 || {
|
||||||
|
echo "nix is still unavailable after bootstrap" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
65
Scripts/ci/publish-forgejo-release.sh
Executable file
65
Scripts/ci/publish-forgejo-release.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${API_URL:?API_URL is required}"
|
||||||
|
: "${REPOSITORY:?REPOSITORY is required}"
|
||||||
|
: "${RELEASE_TAG:?RELEASE_TAG is required}"
|
||||||
|
: "${TOKEN:?TOKEN is required}"
|
||||||
|
|
||||||
|
release_api="${API_URL}/repos/${REPOSITORY}/releases"
|
||||||
|
tag_api="${release_api}/tags/${RELEASE_TAG}"
|
||||||
|
release_json="$(mktemp)"
|
||||||
|
create_json="$(mktemp)"
|
||||||
|
trap 'rm -f "${release_json}" "${create_json}"' EXIT
|
||||||
|
|
||||||
|
status="$(
|
||||||
|
curl -sS -o "${release_json}" -w '%{http_code}' \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
"${tag_api}"
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ "${status}" == "404" ]]; then
|
||||||
|
jq -n \
|
||||||
|
--arg tag "${RELEASE_TAG}" \
|
||||||
|
--arg name "Burrow ${RELEASE_TAG}" \
|
||||||
|
'{
|
||||||
|
tag_name: $tag,
|
||||||
|
target_commitish: $tag,
|
||||||
|
name: $name,
|
||||||
|
body: "Automated prerelease built on Forgejo Namespace runners.",
|
||||||
|
draft: false,
|
||||||
|
prerelease: true
|
||||||
|
}' > "${create_json}"
|
||||||
|
|
||||||
|
curl -fsS \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d @"${create_json}" \
|
||||||
|
"${release_api}" > "${release_json}"
|
||||||
|
elif [[ "${status}" != "200" ]]; then
|
||||||
|
echo "failed to query Forgejo release for ${RELEASE_TAG} (HTTP ${status})" >&2
|
||||||
|
cat "${release_json}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
release_id="$(jq -r '.id' "${release_json}")"
|
||||||
|
if [[ -z "${release_id}" || "${release_id}" == "null" ]]; then
|
||||||
|
echo "Forgejo release payload is missing an id" >&2
|
||||||
|
cat "${release_json}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in dist/*; do
|
||||||
|
name="$(basename "${file}")"
|
||||||
|
asset_id="$(jq -r --arg name "${name}" '.assets[]? | select(.name == $name) | .id' "${release_json}" | head -n1)"
|
||||||
|
if [[ -n "${asset_id}" ]]; then
|
||||||
|
curl -fsS -X DELETE \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
"${release_api}/${release_id}/assets/${asset_id}" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -fsS \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-F "attachment=@${file}" \
|
||||||
|
"${release_api}/${release_id}/assets?name=${name}" >/dev/null
|
||||||
|
done
|
||||||
Loading…
Add table
Add a link
Reference in a new issue