diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml index 5b3ec49..1b8e964 100644 --- a/.gitea/workflows/publish.yml +++ b/.gitea/workflows/publish.yml @@ -1,46 +1,94 @@ name: Publish release -# A `v*` tag builds the binary and attaches it to the Gitea release as -# `gdo`, with the tag's CHANGELOG.md section as the notes. Hosts -# install it with deploy/install.sh. +# A `v*` tag builds the package on each architecture's own runner +# (x86_64 on ergo's bare runner, aarch64 on klokka's) and uploads it +# to the [uhhm] Arch registry, like uhhm/corp and cnats. Hosts then +# `pacman -S gdo`. The tag has to agree with PKGBUILD's pkgver, and +# CHANGELOG.md has to have the section; a release with the tag's notes +# is created from the x86_64 job for the record, with no asset. on: push: tags: ["v*"] jobs: - publish: - runs-on: bare + package: + strategy: + matrix: + include: + - arch: x86_64 + runs-on: bare + # The bare runner's shared toolchain and caches, with the + # writable cargo home uhhm/iris uses. + cargo_home: /var/local/cargo-target/iris-cargo-home + rustc_wrapper: /usr/bin/sccache + rustup_home: /var/local/rustup + target_dir: /var/local/cargo-target + - arch: aarch64 + runs-on: aarch64 + # klokka's host runner: the system cargo, defaults everywhere. + cargo_home: "" + rustc_wrapper: "" + rustup_home: "" + target_dir: "" + runs-on: ${{ matrix.runs-on }} env: - CARGO_HOME: /var/local/cargo-target/iris-cargo-home - RUSTC_WRAPPER: /usr/bin/sccache - RUSTUP_HOME: /var/local/rustup + CARGO_HOME: ${{ matrix.cargo_home }} + RUSTC_WRAPPER: ${{ matrix.rustc_wrapper }} + RUSTUP_HOME: ${{ matrix.rustup_home }} + CARGO_TARGET_DIR: ${{ matrix.target_dir }} PATH: /var/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin SCCACHE_DIR: /var/local/sccache SCCACHE_SERVER_PORT: "4228" - CARGO_TARGET_DIR: /var/local/cargo-target steps: - - uses: actions/checkout@v4 + # Plain git: the aarch64 host runner has no Node.js for + # actions/checkout (same as uhhm/corp). + - name: Checkout + run: | + git init -q . + git fetch -q --depth 1 "https://ci:${{ gitea.token }}@${GITEA_SERVER#https://}/${{ gitea.repository }}.git" "${{ gitea.sha }}" + git checkout -q FETCH_HEAD + env: + GITEA_SERVER: ${{ gitea.server_url }} - - name: Build - run: cargo build --release && cargo test --release + - name: Check tag matches pkgver + run: | + want="${GITHUB_REF_NAME#v}" + have=$(sed -n 's/^pkgver=//p' PKGBUILD) + [ "$want" = "$have" ] || { echo "tag $GITHUB_REF_NAME != pkgver $have" >&2; exit 1; } + notes=$(awk -v v="$want" '/^## /{p = ($2 == v)} p' CHANGELOG.md | tail -n +2) + [ -n "$(printf "%s" "$notes" | tr -d "[:space:]")" ] || { echo "CHANGELOG.md has no section for $GITHUB_REF_NAME" >&2; exit 1; } - - name: Publish release + # -d: cargo is the shared toolchain, not a pacman package the + # runner could verify. Builds and tests from the checkout. Empty + # env values above are unset here so cargo's defaults apply. + - name: Build package + run: | + for v in CARGO_HOME RUSTC_WRAPPER RUSTUP_HOME CARGO_TARGET_DIR; do + eval "[ -n \"\$$v\" ]" || unset "$v" + done + makepkg -f -d --noconfirm + + # REGISTRY_TOKEN is a write:package token for bl, a secret on this + # repo (org repos do not inherit bl's). The registry namespace is + # always bl: pacman.conf's [uhhm] points at /api/packages/bl/arch/uhhm. + - name: Publish to the Arch package registry + run: | + for pkg in $(makepkg --packagelist); do + echo "==> $pkg" + curl --fail-with-body --user "bl:${{ secrets.REGISTRY_TOKEN }}" \ + --upload-file "$pkg" \ + "${{ gitea.server_url }}/api/packages/bl/arch/uhhm" + done + + - name: Release notes + if: matrix.arch == 'x86_64' run: | set -euo pipefail tag="${{ github.ref_name }}" api="${{ github.server_url }}/api/v1/repos/${{ github.repository }}" auth="Authorization: token ${{ secrets.GITHUB_TOKEN }}" notes=$(awk -v v="${tag#v}" '/^## /{p = ($2 == v)} p' CHANGELOG.md | tail -n +2) - [ -n "$(printf "%s" "$notes" | tr -d "[:space:]")" ] || { echo "CHANGELOG.md has no section for $tag"; exit 1; } body=$(jq -n --arg tag "$tag" --arg notes "$notes" '{tag_name: $tag, name: $tag, body: $notes}') - id=$(curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' \ - -d "$body" "$api/releases" | jq .id) \ - || id=$(curl -sf -H "$auth" "$api/releases/tags/$tag" | jq .id) - for aid in $(curl -sf -H "$auth" "$api/releases/$id/assets" | jq '.[].id'); do - curl -sf -X DELETE -H "$auth" "$api/releases/$id/assets/$aid" - done - curl -sf -X POST -H "$auth" \ - -F "attachment=@/var/local/cargo-target/release/gdo" \ - "$api/releases/$id/assets?name=gdo" > /dev/null - echo "published $tag" + curl -sf -X POST -H "$auth" -H 'Content-Type: application/json' -d "$body" "$api/releases" > /dev/null \ + || echo "release $tag exists" diff --git a/.gitignore b/.gitignore index eb5a316..fb82ddd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ target +pkg/ +*.pkg.tar.zst diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a640a7..530b35e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.1.1 (2026-09-23) + +- Packaged: `pacman -S gdo` from the [uhhm] registry on project.uhhm.no (x86_64 and aarch64, built by the release workflow from the tagged checkout); the unit and `/etc/gdo/env` ship in the package, and the installer script is gone. + ## 0.1.0 (2026-09-23) - First release: a durable consumer `gdo` on the `WORMHOLE` stream (`portal.mail.>`), each message handed to the host's SMTP as text with an HTML alternative, acked on acceptance and retried after a minute otherwise; `gdo probe
` sends one message through and reports when it was delivered; an optional Typst theme (`GDO_TYPST_THEME`) renders a PDF of every mail and attaches it. diff --git a/Cargo.lock b/Cargo.lock index b3b5e90..bb4827f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -411,7 +411,7 @@ dependencies = [ [[package]] name = "gdo" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "async-nats", diff --git a/Cargo.toml b/Cargo.toml index 81ef77e..8ae9b27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gdo" -version = "0.1.0" +version = "0.1.1" edition = "2021" description = "Sends the code that opens the iris: delivers portal's outgoing mail from JetStream to the host's SMTP" license = "MIT" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..add8a78 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Bendik Aagaard Lynghaug + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..94efb51 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,44 @@ +# Maintainer: Bendik Aagaard Lynghaug