Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8dfd7017b | ||
|
|
99f4cf0220 | ||
|
|
69263b2dd9 | ||
|
|
20444013c0 | ||
|
|
2196f6635b | ||
|
|
6438982d45 |
No files matched your search
@@ -0,0 +1,215 @@
|
||||
name: Release
|
||||
|
||||
# Build the agent for every supported target on a version tag, leave each build
|
||||
# as a run artifact, and then — only after every target has built — attach the
|
||||
# archives to the release. Linux is a fully static musl binary (built with
|
||||
# cargo-zigbuild) so one artifact runs on any distro and can be repackaged
|
||||
# however a distro prefers.
|
||||
#
|
||||
# Targeted at Gitea Actions: artifacts use @v3 (the v4 backend is not available
|
||||
# on Gitea/GHES), and the release is filled through Gitea's own API with curl
|
||||
# rather than `gh`, which speaks only to github.com.
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
CARGO_NET_RETRY: "10"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.asset }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-musl
|
||||
asset: tsunagi-linux-x86_64
|
||||
archive: tar.gz
|
||||
zig: true
|
||||
- os: ubuntu-latest
|
||||
target: aarch64-unknown-linux-musl
|
||||
asset: tsunagi-linux-aarch64
|
||||
archive: tar.gz
|
||||
zig: true
|
||||
- os: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
asset: tsunagi-macos-aarch64
|
||||
archive: tar.gz
|
||||
zig: false
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
asset: tsunagi-windows-x86_64
|
||||
archive: zip
|
||||
zig: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
|
||||
# aws-lc-sys (iroh's rustls backend) and the bundled sqlite are C, and the
|
||||
# musl targets have no prebuilt bindings, so bindgen needs libclang and the
|
||||
# C build needs cmake. zig is the cross C compiler cargo-zigbuild drives.
|
||||
- name: Install musl build tooling
|
||||
if: matrix.zig
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends cmake clang libclang-dev
|
||||
- name: Install zig
|
||||
if: matrix.zig
|
||||
uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
# Pin a real, archived Zig release. Left unpinned the action resolves
|
||||
# to the newest version it knows of (a yet-unreleased 0.16.0-dev),
|
||||
# whose tarball 404s on ziglang.org while the community mirrors flake.
|
||||
version: 0.14.1
|
||||
- name: Install cargo-zigbuild
|
||||
if: matrix.zig
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-zigbuild
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${{ matrix.zig }}" == "true" ]]; then
|
||||
# zig's linker ignores the `-O1` GNU-ld optimization flag Rust passes
|
||||
# and says so on stderr, which rustc now surfaces as a linker_messages
|
||||
# warning. It is cosmetic — the binary is correct — so quiet just that
|
||||
# one lint to keep the musl build log clean. A real link error still
|
||||
# fails the build.
|
||||
export RUSTFLAGS="${RUSTFLAGS:-} -A linker_messages"
|
||||
cargo zigbuild --release --locked --target "${{ matrix.target }}" --bin tsunagi
|
||||
else
|
||||
cargo build --release --locked --target "${{ matrix.target }}" --bin tsunagi
|
||||
fi
|
||||
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
version="${GITHUB_REF_NAME#v}"
|
||||
stage="dist/pkg/${{ matrix.asset }}"
|
||||
mkdir -p "$stage"
|
||||
|
||||
bin="tsunagi"
|
||||
[[ "${{ runner.os }}" == "Windows" ]] && bin="tsunagi.exe"
|
||||
cp "target/${{ matrix.target }}/release/${bin}" "$stage/"
|
||||
|
||||
# The top-level README, plus the per-OS install notes and integration
|
||||
# files, so the archive carries what the platform needs to set up.
|
||||
cp README.md "$stage/"
|
||||
case "${{ runner.os }}" in
|
||||
Linux)
|
||||
cp dist/linux/tsunagi.service dist/linux/install.sh "$stage/"
|
||||
cp dist/linux/README.md "$stage/INSTALL.md"
|
||||
;;
|
||||
macOS)
|
||||
cp dist/macos/cy.hexor.tsunagi.plist "$stage/"
|
||||
cp dist/macos/README.md "$stage/INSTALL.md"
|
||||
;;
|
||||
Windows)
|
||||
cp dist/windows/README.md "$stage/INSTALL.md"
|
||||
;;
|
||||
esac
|
||||
|
||||
archive="${{ matrix.asset }}-${version}.${{ matrix.archive }}"
|
||||
if [[ "${{ matrix.archive }}" == "zip" ]]; then
|
||||
(cd dist/pkg && 7z a "../../${archive}" "${{ matrix.asset }}")
|
||||
else
|
||||
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
||||
fi
|
||||
|
||||
# @v3 on purpose: Gitea does not support the v4 artifact backend. This is
|
||||
# what makes the archive show up under the run and hands it to `publish`.
|
||||
- name: Upload the archive as a run artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: ${{ matrix.asset }}-*.*
|
||||
if-no-files-found: error
|
||||
|
||||
publish:
|
||||
name: Publish release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download every build artifact
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Show what was collected
|
||||
run: find artifacts -type f
|
||||
|
||||
- name: Create the release and upload the archives
|
||||
shell: bash
|
||||
env:
|
||||
# Gitea injects this with access to the current repository. If the
|
||||
# release calls below return 403, the repo/runner is configured to
|
||||
# hand Actions a read-only token — grant it write access to releases.
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -u
|
||||
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
# Gitea sets GITHUB_API_URL to its own API root (…/api/v1); fall back
|
||||
# to building it from the server URL if it is absent.
|
||||
base="${GITHUB_API_URL:-${GITHUB_SERVER_URL}/api/v1}"
|
||||
api="${base}/repos/${GITHUB_REPOSITORY}"
|
||||
auth="Authorization: token ${TOKEN}"
|
||||
echo "release API: $api"
|
||||
|
||||
prerelease=false
|
||||
case "$tag" in *-*) prerelease=true ;; esac
|
||||
|
||||
# The release id for this tag, if it already exists.
|
||||
code=$(curl -sS -o resp.json -w '%{http_code}' -H "$auth" "$api/releases/tags/$tag" || true)
|
||||
echo "get release by tag: HTTP $code"
|
||||
id=$(grep -o '"id":[0-9]*' resp.json 2>/dev/null | head -n1 | cut -d: -f2 || true)
|
||||
|
||||
if [ -z "$id" ]; then
|
||||
code=$(curl -sS -o resp.json -w '%{http_code}' -X POST -H "$auth" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"tag_name\":\"$tag\",\"name\":\"tsunagi $tag\",\"prerelease\":$prerelease}" \
|
||||
"$api/releases" || true)
|
||||
echo "create release: HTTP $code"
|
||||
id=$(grep -o '"id":[0-9]*' resp.json 2>/dev/null | head -n1 | cut -d: -f2 || true)
|
||||
if [ -z "$id" ]; then
|
||||
echo "could not create the release; response was:" >&2
|
||||
cat resp.json >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "release id: $id"
|
||||
|
||||
# download-artifact@v3 nests each artifact in a directory named after
|
||||
# its upload, with the single archive inside. The read loop runs in
|
||||
# this shell (process substitution, not a pipe) so a failed upload
|
||||
# actually fails the job.
|
||||
rc=0
|
||||
while IFS= read -r -d '' f; do
|
||||
name=$(basename "$f")
|
||||
code=$(curl -sS -o up.json -w '%{http_code}' -X POST -H "$auth" \
|
||||
-F "attachment=@${f}" \
|
||||
"$api/releases/$id/assets?name=${name}" || true)
|
||||
echo "upload $name: HTTP $code"
|
||||
if [ "$code" -lt 200 ] || [ "$code" -ge 300 ]; then
|
||||
cat up.json >&2 || true
|
||||
rc=1
|
||||
fi
|
||||
done < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' \) -print0)
|
||||
exit "$rc"
|
||||
@@ -1,15 +1,25 @@
|
||||
name: Release
|
||||
|
||||
# Build the agent for every supported target on a version tag and attach the
|
||||
# archives to a GitHub release. Linux is a fully static musl binary (built with
|
||||
# cargo-zigbuild) so one artifact runs on any distro — Arch, Alpine, NixOS, old
|
||||
# glibc systems alike — and can then be repackaged however a distro prefers.
|
||||
# GitHub version of the release pipeline. The build half mirrors the Gitea one
|
||||
# in .gitea/workflows/release.yml (static musl Linux via cargo-zigbuild, native
|
||||
# macOS and Windows); only the publish half differs: GitHub needs the v4
|
||||
# artifact backend and fills the release with `gh`.
|
||||
#
|
||||
# Gitea reads both .gitea/workflows and .github/workflows, so without a guard it
|
||||
# would also try to run this file and fail on @v4 and `gh`. (Gitea reports
|
||||
# github.server_url as https://github.com, so that cannot tell the two apart.)
|
||||
# Instead every job is gated on a repository variable GITHUB_RELEASE=true, which
|
||||
# is set only in the GitHub repository's settings — so on Gitea, where it is
|
||||
# absent, these jobs are skipped and the .gitea file is the one that runs.
|
||||
#
|
||||
# To enable on GitHub: Settings → Secrets and variables → Actions → Variables →
|
||||
# New variable, name GITHUB_RELEASE, value true.
|
||||
on:
|
||||
push:
|
||||
tags: ["v*"]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -18,6 +28,7 @@ env:
|
||||
jobs:
|
||||
build:
|
||||
name: ${{ matrix.asset }}
|
||||
if: ${{ vars.GITHUB_RELEASE == 'true' }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -66,11 +77,8 @@ jobs:
|
||||
uses: mlugg/setup-zig@v2
|
||||
with:
|
||||
# Pin a real, archived Zig release. Left unpinned the action resolves
|
||||
# to the newest version it knows of (a yet-unreleased 0.16.0-dev here),
|
||||
# whose tarball 404s on ziglang.org while the community mirrors flake —
|
||||
# exactly the failure this build hit. A concrete release always has a
|
||||
# permanent official URL, so the download succeeds even if mirrors are
|
||||
# down, and the version stays compatible with cargo-zigbuild.
|
||||
# to the newest version it knows of (a yet-unreleased 0.16.0-dev),
|
||||
# whose tarball 404s on ziglang.org while the community mirrors flake.
|
||||
version: 0.14.1
|
||||
- name: Install cargo-zigbuild
|
||||
if: matrix.zig
|
||||
@@ -83,6 +91,12 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${{ matrix.zig }}" == "true" ]]; then
|
||||
# zig's linker ignores the `-O1` GNU-ld optimization flag Rust passes
|
||||
# and says so on stderr, which rustc now surfaces as a linker_messages
|
||||
# warning. It is cosmetic — the binary is correct — so quiet just that
|
||||
# one lint to keep the musl build log clean. A real link error still
|
||||
# fails the build.
|
||||
export RUSTFLAGS="${RUSTFLAGS:-} -A linker_messages"
|
||||
cargo zigbuild --release --locked --target "${{ matrix.target }}" --bin tsunagi
|
||||
else
|
||||
cargo build --release --locked --target "${{ matrix.target }}" --bin tsunagi
|
||||
@@ -125,7 +139,8 @@ jobs:
|
||||
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
||||
fi
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- name: Upload the archive as a run artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: ${{ matrix.asset }}-*.*
|
||||
@@ -134,23 +149,44 @@ jobs:
|
||||
publish:
|
||||
name: Publish release
|
||||
needs: build
|
||||
if: ${{ vars.GITHUB_RELEASE == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: Download every build artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Create release and upload assets
|
||||
- name: Show what was collected
|
||||
run: find artifacts -type f
|
||||
|
||||
- name: Create the release and upload the archives
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
gh release create "$RELEASE_TAG" artifacts/*/* \
|
||||
--title "tsunagi ${RELEASE_TAG}" \
|
||||
--generate-notes \
|
||||
--verify-tag
|
||||
|
||||
# download-artifact@v4 nests each artifact under its own directory, so
|
||||
# the archives are artifacts/<asset>/<file>.
|
||||
mapfile -t files < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' \))
|
||||
printf 'asset: %s\n' "${files[@]}"
|
||||
|
||||
prerelease=()
|
||||
case "$TAG" in *-*) prerelease=(--prerelease) ;; esac
|
||||
|
||||
# Create the release on the first run; on a re-run, add/replace assets
|
||||
# on the release that is already there.
|
||||
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
||||
gh release upload "$TAG" "${files[@]}" --repo "$GITHUB_REPOSITORY" --clobber
|
||||
else
|
||||
gh release create "$TAG" "${files[@]}" \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--title "tsunagi $TAG" \
|
||||
--generate-notes \
|
||||
--verify-tag \
|
||||
"${prerelease[@]}"
|
||||
fi
|
||||
Reference in new issue
Block a user