Files
nyaterm/.github/workflows/publish-aur.yml
T

238 lines
9.5 KiB
YAML

name: Publish AUR package
on:
workflow_run:
workflows: ['Release']
types: [completed]
workflow_dispatch:
inputs:
version:
description: Stable version, with or without v prefix
required: true
type: string
dry_run:
description: Validate changes without pushing to AUR
required: false
default: false
type: boolean
permissions:
actions: read
contents: read
concurrency:
group: aur-nyaterm-bin
cancel-in-progress: false
env:
AUR_REPO: ssh://aur@aur.archlinux.org/nyaterm-bin.git
UPSTREAM_REPO: nyakang/nyaterm
jobs:
publish:
name: Publish nyaterm-bin
if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Resolve stable release tag
id: release
shell: bash
env:
GH_TOKEN: ${{ github.token }}
INPUT_VERSION: ${{ inputs.version }}
INPUT_DRY_RUN: ${{ inputs.dry_run }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
set -euo pipefail
publish='true'
dry_run="${INPUT_DRY_RUN:-false}"
if [[ "${GITHUB_EVENT_NAME}" == 'workflow_dispatch' ]]; then
version="${INPUT_VERSION#v}"
else
r2_success="$(gh api "repos/${GITHUB_REPOSITORY}/actions/runs/${RUN_ID}/jobs?per_page=100" \
--jq '[.jobs[] | select(.name == "Publish Cloudflare R2 mirror" and .conclusion == "success")] | length')"
if [[ "${r2_success}" == '1' ]]; then
receipt_dir="$(mktemp -d)"
trap 'rm -rf "${receipt_dir}"' EXIT
gh run download "${RUN_ID}" --repo "${GITHUB_REPOSITORY}" \
--name published-release-tag --dir "${receipt_dir}"
tag="$(cat "${receipt_dir}/published-release-tag.txt")"
version="${tag#v}"
else
version=''
fi
fi
if [[ -z "${version}" || "${version}" == *-* || ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
publish='false'
fi
if [[ "${publish}" == 'true' ]]; then
release_state="$(gh release view "v${version}" --repo "${GITHUB_REPOSITORY}" \
--json isDraft,isPrerelease,tagName --jq '[.isDraft,.isPrerelease,.tagName] | @tsv')"
expected="$(printf 'false\tfalse\tv%s' "${version}")"
[[ "${release_state}" == "${expected}" ]] || {
echo "Release v${version} is not a published stable release" >&2
exit 1
}
fi
{
echo "publish=${publish}"
echo "version=${version}"
echo "tag=v${version}"
echo "dry_run=${dry_run}"
} >> "${GITHUB_OUTPUT}"
- name: Skip non-stable release
if: steps.release.outputs.publish != 'true'
run: echo 'No stable AUR release to publish.'
- name: Configure AUR SSH
if: steps.release.outputs.publish == 'true'
shell: bash
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
set -euo pipefail
[[ -n "${AUR_SSH_PRIVATE_KEY:-}" ]] || { echo 'AUR_SSH_PRIVATE_KEY is required' >&2; exit 1; }
install -d -m 700 ~/.ssh
printf '%s\n' "${AUR_SSH_PRIVATE_KEY}" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan -t ed25519 aur.archlinux.org >> ~/.ssh/known_hosts
cat > ~/.ssh/config <<'EOF'
Host aur.archlinux.org
User aur
IdentityFile ~/.ssh/aur
IdentitiesOnly yes
StrictHostKeyChecking yes
EOF
- name: Clone AUR repository
if: steps.release.outputs.publish == 'true'
run: git clone "${AUR_REPO}" aur
- name: Download and inspect GPUI packages
if: steps.release.outputs.publish == 'true'
id: assets
shell: bash
env:
TAG: ${{ steps.release.outputs.tag }}
VERSION: ${{ steps.release.outputs.version }}
run: |
set -euo pipefail
mkdir packages
base="https://github.com/${UPSTREAM_REPO}/releases/download/${TAG}"
curl -fL --retry 5 "https://raw.githubusercontent.com/${UPSTREAM_REPO}/${TAG}/LICENSE" -o packages/LICENSE
curl -fL --retry 5 "${base}/NyaTerm_${VERSION}_linux_x64.deb" -o packages/x64.deb
curl -fL --retry 5 "${base}/NyaTerm_${VERSION}_linux_arm64.deb" -o packages/arm64.deb
test "$(dpkg-deb -f packages/x64.deb Package)" = nyaterm
test "$(dpkg-deb -f packages/arm64.deb Package)" = nyaterm
for package in packages/*.deb; do
contents="$(dpkg-deb --contents "${package}")"
grep -q './opt/nyaterm/nyaterm' <<< "${contents}"
grep -q './opt/nyaterm/nyaterm-rdp-helper' <<< "${contents}"
grep -q './opt/nyaterm/nyaterm-vnc-helper' <<< "${contents}"
grep -q './opt/nyaterm/nyaterm-mcp' <<< "${contents}"
done
{
echo "license_sha=$(sha256sum packages/LICENSE | awk '{print $1}')"
echo "x64_sha=$(sha256sum packages/x64.deb | awk '{print $1}')"
echo "arm64_sha=$(sha256sum packages/arm64.deb | awk '{print $1}')"
} >> "${GITHUB_OUTPUT}"
- name: Write GPUI PKGBUILD
if: steps.release.outputs.publish == 'true'
shell: bash
env:
ARM64_SHA: ${{ steps.assets.outputs.arm64_sha }}
LICENSE_SHA: ${{ steps.assets.outputs.license_sha }}
VERSION: ${{ steps.release.outputs.version }}
X64_SHA: ${{ steps.assets.outputs.x64_sha }}
run: |
set -euo pipefail
python3 - <<'PY'
import os
from pathlib import Path
version = os.environ["VERSION"]
shell_version = "${pkgver}"
text = f'''# Maintainer: dydydd <admin@lidream.cn>
# Co-Maintainer: NyaKang <CoderKang@hotmail.com>
pkgname=nyaterm-bin
pkgver={version}
pkgrel=1
pkgdesc="Native GPUI terminal workspace with SSH, SFTP, RDP and VNC"
arch=('x86_64' 'aarch64')
url="https://github.com/nyakang/nyaterm"
license=('Apache-2.0')
options=(!debug)
depends=('dbus' 'fontconfig' 'freetype2' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libx11' 'libxcb' 'libxkbcommon' 'libxkbcommon-x11' 'openssl' 'systemd-libs' 'wayland' 'zstd')
optdepends=('vulkan-icd-loader: Vulkan loader required by GPUI' 'vulkan-driver: hardware-specific Vulkan implementation')
source=("LICENSE::$url/raw/v$pkgver/LICENSE")
source_x86_64=("$pkgname-$pkgver-x86_64.deb::$url/releases/download/v$pkgver/NyaTerm_{shell_version}_linux_x64.deb")
source_aarch64=("$pkgname-$pkgver-aarch64.deb::$url/releases/download/v$pkgver/NyaTerm_{shell_version}_linux_arm64.deb")
sha256sums=('{os.environ["LICENSE_SHA"]}')
sha256sums_x86_64=('{os.environ["X64_SHA"]}')
sha256sums_aarch64=('{os.environ["ARM64_SHA"]}')
package() {{
local deb="$srcdir/$pkgname-$pkgver-$CARCH.deb"
local unpack="$srcdir/deb-payload"
rm -rf "$unpack"
mkdir -p "$unpack" "$pkgdir"
cd "$unpack"
ar x "$deb"
bsdtar -xf data.tar.* -C "$pkgdir"
install -d "$pkgdir/usr/bin" "$pkgdir/usr/share/licenses/$pkgname"
ln -s /opt/nyaterm/nyaterm "$pkgdir/usr/bin/nyaterm"
install -m644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}}
'''
Path("aur/PKGBUILD").write_text("\n".join(line[10:] if line.startswith(" ") else line for line in text.splitlines()) + "\n")
Path("aur/nyaterm.sh").unlink(missing_ok=True)
PY
- name: Validate and build AUR package
if: steps.release.outputs.publish == 'true'
shell: bash
run: |
set -euo pipefail
docker run --rm -v "${PWD}/aur:/pkg" archlinux:base-devel bash -lc '
set -euo pipefail
pacman -Sy --noconfirm namcap
useradd -m builder
chown -R builder:builder /pkg
su builder -c "cd /pkg && bash -n PKGBUILD && makepkg --printsrcinfo > .SRCINFO && makepkg --nodeps --noconfirm --cleanbuild"
namcap /pkg/PKGBUILD /pkg/*.pkg.tar.zst
# bsdtar is available in the Arch image, not the Ubuntu host.
contents="$(bsdtar -tf /pkg/*.pkg.tar.zst)"
for binary in nyaterm nyaterm-rdp-helper nyaterm-vnc-helper nyaterm-mcp; do
grep -q "opt/nyaterm/${binary}$" <<< "${contents}" || {
echo "missing bundled binary: ${binary}" >&2
exit 1
}
done
'
sudo chown -R "${USER}:${USER}" aur
grep -q "pkgver = ${{ steps.release.outputs.version }}" aur/.SRCINFO
- name: Commit and push AUR update
if: steps.release.outputs.publish == 'true'
working-directory: aur
env:
DRY_RUN: ${{ steps.release.outputs.dry_run }}
VERSION: ${{ steps.release.outputs.version }}
run: |
set -euo pipefail
git config user.name NyaKang
git config user.email CoderKang@hotmail.com
git add -A
git diff --cached --check
if git diff --cached --quiet; then exit 0; fi
if [[ "${DRY_RUN}" == 'true' ]]; then
git diff --cached
exit 0
fi
git commit -m "Update to ${VERSION}"
git push origin master