Repository navigation
Kova v0.7.8 #69
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish Package Repos | |
| # Fires when a draft release is manually published | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Release tag to publish (e.g. v0.2.2)' | |
| required: false | |
| default: '' | |
| jobs: | |
| publish-repos: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Install repo tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y dpkg-dev apt-utils createrepo-c rsync rpm | |
| - name: Resolve release tag | |
| run: | | |
| TAG="${{ github.event.release.tag_name || inputs.tag }}" | |
| if [ -z "$TAG" ]; then | |
| TAG=$(gh release list --repo ${{ github.repository }} --limit 1 --json tagName -q '.[0].tagName') | |
| fi | |
| echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download release assets | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release download "$RELEASE_TAG" \ | |
| --pattern "*.deb" --pattern "*.rpm" \ | |
| --dir assets \ | |
| --repo ${{ github.repository }} | |
| - name: Import GPG signing key | |
| run: | | |
| echo "${{ secrets.GPG_PRIVATE_KEY }}" | gpg --batch --import | |
| GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec/{print $5; exit}') | |
| echo "GPG_KEY_ID=$GPG_KEY_ID" >> $GITHUB_ENV | |
| - name: Build APT repo | |
| run: | | |
| mkdir -p repo/deb/pool/main repo/deb/dists/stable/main/binary-amd64 | |
| cp assets/*.deb repo/deb/pool/main/ | |
| cd repo/deb | |
| dpkg-scanpackages pool/main > dists/stable/main/binary-amd64/Packages | |
| gzip -k dists/stable/main/binary-amd64/Packages | |
| apt-ftparchive \ | |
| -o APT::FTPArchive::Release::Origin=Kova \ | |
| -o APT::FTPArchive::Release::Label=Kova \ | |
| -o APT::FTPArchive::Release::Suite=stable \ | |
| -o APT::FTPArchive::Release::Codename=stable \ | |
| -o APT::FTPArchive::Release::Architectures=amd64 \ | |
| -o APT::FTPArchive::Release::Components=main \ | |
| release dists/stable > dists/stable/Release | |
| gpg --batch \ | |
| --passphrase "${{ secrets.GPG_PASSPHRASE }}" \ | |
| --pinentry-mode loopback \ | |
| --clearsign -o dists/stable/InRelease dists/stable/Release | |
| gpg --batch \ | |
| --passphrase "${{ secrets.GPG_PASSPHRASE }}" \ | |
| --pinentry-mode loopback \ | |
| -abs -o dists/stable/Release.gpg dists/stable/Release | |
| # Public key for users to add | |
| gpg --armor --export "$GPG_KEY_ID" > key.gpg | |
| - name: Build RPM repo | |
| env: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| run: | | |
| mkdir -p repo/rpm | |
| cp assets/*.rpm repo/rpm/ | |
| # Sign RPMs inside a Fedora container — Ubuntu's RPM macros are | |
| # incomplete for signing; Fedora is the native RPM signing environment | |
| docker run --rm \ | |
| -v "$(pwd)/repo/rpm:/rpm" \ | |
| -e GPG_PRIVATE_KEY="$GPG_PRIVATE_KEY" \ | |
| -e GPG_KEY_ID="$GPG_KEY_ID" \ | |
| fedora:latest bash -c ' | |
| dnf install -y rpm-sign gnupg2 -q 2>/dev/null | |
| # Use isolated GNUPGHOME with agent disabled so GPG | |
| # operates directly without needing a TTY | |
| export GNUPGHOME=/tmp/gnupg | |
| mkdir -p $GNUPGHOME && chmod 700 $GNUPGHOME | |
| printf "no-tty\nbatch\npinentry-mode loopback\n" > $GNUPGHOME/gpg.conf | |
| printf "allow-loopback-pinentry\n" > $GNUPGHOME/gpg-agent.conf | |
| gpg-agent --daemon --homedir $GNUPGHOME 2>/dev/null || true | |
| echo "$GPG_PRIVATE_KEY" | gpg --batch --import | |
| gpg --list-secret-keys | |
| # Import public key into RPM keyring for checksig verification | |
| gpg --armor --export "$GPG_KEY_ID" > /tmp/pub.asc | |
| rpm --import /tmp/pub.asc | |
| echo "%_gpg_name $GPG_KEY_ID" > ~/.rpmmacros | |
| rpmsign --resign /rpm/*.rpm | |
| rpm --checksig /rpm/*.rpm | |
| ' | |
| createrepo_c repo/rpm | |
| # Sign the repo metadata | |
| gpg --batch \ | |
| --passphrase "$GPG_PASSPHRASE" \ | |
| --pinentry-mode loopback \ | |
| --detach-sign --armor repo/rpm/repodata/repomd.xml | |
| cat > repo/rpm/kova.repo << 'EOF' | |
| [kova] | |
| name=Kova | |
| baseurl=https://rpm.kova.md | |
| enabled=1 | |
| gpgcheck=1 | |
| repo_gpgcheck=1 | |
| gpgkey=https://rpm.kova.md/key.gpg | |
| EOF | |
| gpg --armor --export "$GPG_KEY_ID" > repo/rpm/key.gpg | |
| - name: Deploy to VPS | |
| env: | |
| SSH_KEY: ${{ secrets.HETZNER_SSH_KEY }} | |
| HOST: ${{ secrets.HETZNER_HOST }} | |
| USER: ${{ secrets.HETZNER_USER }} | |
| # Populate with: ssh-keyscan <host> 2>/dev/null | |
| KNOWN_HOSTS: ${{ secrets.HETZNER_KNOWN_HOSTS }} | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts | |
| chmod 600 ~/.ssh/known_hosts | |
| echo "$SSH_KEY" > /tmp/deploy_key | |
| chmod 600 /tmp/deploy_key | |
| SSH_OPTS="-i /tmp/deploy_key -o StrictHostKeyChecking=yes" | |
| rsync -avz --delete -e "ssh $SSH_OPTS" \ | |
| repo/deb/ $USER@$HOST:/opt/kova/deb-repo/data/ | |
| rsync -avz --delete -e "ssh $SSH_OPTS" \ | |
| repo/rpm/ $USER@$HOST:/opt/kova/rpm-repo/data/ | |
| rm /tmp/deploy_key | |
| # Repacks the release .deb into a signed Flatpak ostree repo (Flathub is out — | |
| # its no-LLM policy), served at flatpak.kova.md by the flatpak-repo service in | |
| # infra/services. Needs the DNS record for flatpak.kova.md, like deb/rpm. | |
| publish-flatpak: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 | |
| - name: Install Flatpak tooling + GNOME runtime | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y flatpak flatpak-builder rsync | |
| curl -fsSL https://dl.flathub.org/repo/flathub.gpg -o /tmp/flathub.gpg | |
| flatpak remote-add --user --if-not-exists flathub \ | |
| https://dl.flathub.org/repo/ --gpg-import=/tmp/flathub.gpg | |
| flatpak install --user -y --noninteractive flathub org.gnome.Platform//49 org.gnome.Sdk//49 | |
| - name: Resolve release tag | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="${{ github.event.release.tag_name || inputs.tag }}" | |
| if [ -z "$TAG" ]; then | |
| TAG=$(gh release list --repo ${{ github.repository }} --limit 1 --json tagName -q '.[0].tagName') | |
| fi | |
| echo "RELEASE_TAG=$TAG" >> $GITHUB_ENV | |
| - name: Download release .deb | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release download "$RELEASE_TAG" --pattern "Kova_Linux.deb" \ | |
| --dir packaging/flatpak --repo ${{ github.repository }} | |
| mv packaging/flatpak/Kova_Linux.deb packaging/flatpak/kova.deb | |
| # Stamp this release into the metainfo so software centers show the | |
| # right version — the checked-in value is a placeholder, not per-release. | |
| sed -i "s|<release version=\"[^\"]*\" date=\"[^\"]*\"/>|<release version=\"${RELEASE_TAG#v}\" date=\"$(date +%F)\"/>|" \ | |
| packaging/flatpak/md.kova.app.metainfo.xml | |
| - name: Import GPG key and preset passphrase for signing | |
| env: | |
| GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} | |
| GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} | |
| run: | | |
| echo "$GPG_PRIVATE_KEY" | gpg --batch --import | |
| GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec/{print $5; exit}') | |
| echo "GPG_KEY_ID=$GPG_KEY_ID" >> $GITHUB_ENV | |
| # flatpak-builder/ostree invoke gpg themselves (no way to pass | |
| # --passphrase per call as the deb/rpm job does), so preset it into the | |
| # agent for unattended signing. | |
| echo "allow-preset-passphrase" >> ~/.gnupg/gpg-agent.conf | |
| gpgconf --reload gpg-agent | |
| PRESET=$(find /usr/lib -name gpg-preset-passphrase 2>/dev/null | head -1) | |
| # Preset every keygrip (primary + any signing subkey) — whichever gpg | |
| # picks to sign is then cached, regardless of the key's shape. | |
| gpg --batch --with-keygrip --list-secret-keys "$GPG_KEY_ID" \ | |
| | awk '/Keygrip/{print $3}' \ | |
| | while read -r grip; do "$PRESET" --preset --passphrase "$GPG_PASSPHRASE" "$grip"; done | |
| - name: Deploy signed Flatpak repo to VPS | |
| env: | |
| SSH_KEY: ${{ secrets.HETZNER_SSH_KEY }} | |
| HOST: ${{ secrets.HETZNER_HOST }} | |
| USER: ${{ secrets.HETZNER_USER }} | |
| KNOWN_HOSTS: ${{ secrets.HETZNER_KNOWN_HOSTS }} | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts | |
| chmod 600 ~/.ssh/known_hosts | |
| echo "$SSH_KEY" > /tmp/deploy_key | |
| chmod 600 /tmp/deploy_key | |
| SSH_OPTS="-i /tmp/deploy_key -o StrictHostKeyChecking=yes" | |
| REMOTE=/opt/kova/flatpak-repo/data | |
| # Pull the existing repo so prior versions' objects (and static deltas) | |
| # survive the --delete push below. ssh-mkdir first so the first run has | |
| # an (empty) source; no `|| true` — a flaky pull must abort here, else | |
| # we'd rebuild from nothing and --delete would wipe every past version. | |
| mkdir -p repo/flatpak | |
| ssh $SSH_OPTS "$USER@$HOST" "mkdir -p $REMOTE" | |
| rsync -az -e "ssh $SSH_OPTS" $USER@$HOST:$REMOTE/ repo/flatpak/ | |
| flatpak-builder --user --force-clean --disable-rofiles-fuse \ | |
| --gpg-sign="$GPG_KEY_ID" --gpg-homedir="$HOME/.gnupg" \ | |
| --repo=repo/flatpak build packaging/flatpak/md.kova.app.yml | |
| flatpak build-update-repo --generate-static-deltas --prune \ | |
| --gpg-sign="$GPG_KEY_ID" --gpg-homedir="$HOME/.gnupg" repo/flatpak | |
| # One-click install descriptor + public key. | |
| gpg --export "$GPG_KEY_ID" > repo/flatpak/kova.gpg | |
| cat > repo/flatpak/kova.flatpakref << EOF | |
| [Flatpak Ref] | |
| Title=Kova | |
| Name=md.kova.app | |
| Branch=master | |
| Url=https://flatpak.kova.md | |
| SuggestRemoteName=kova | |
| GPGKey=$(gpg --export "$GPG_KEY_ID" | base64 -w0) | |
| IsRuntime=false | |
| RuntimeRepo=https://dl.flathub.org/repo/flathub.flatpakrepo | |
| EOF | |
| rsync -avz --delete -e "ssh $SSH_OPTS" repo/flatpak/ $USER@$HOST:$REMOTE/ | |
| rm /tmp/deploy_key |