name: Packages
on:
push:
branches: [main]
paths: ["packaging/**", "src/main.rs", "src/tls/**", "Cargo.toml", ".github/workflows/packaging.yml"]
pull_request:
paths: ["packaging/**", "src/main.rs", "src/tls/**", "Cargo.toml", ".github/workflows/packaging.yml"]
workflow_dispatch:
env:
NFPM_VERSION: 2.47.0
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-musl
- run: sudo apt-get update && sudo apt-get install -y musl-tools
- uses: Swatinem/rust-cache@v2
with:
key: packaging
- name: Build (as the release does)
run: |
cargo build --release --bin rws --features "acme auth sso mimalloc wasm-plugins storage-s3" --target x86_64-unknown-linux-musl
- name: Install nfpm
run: |
curl -sSfL "https://github.com/goreleaser/nfpm/releases/download/v$NFPM_VERSION/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" \
| sudo tar xz -C /usr/local/bin nfpm
- name: Throwaway signing key
run: |
gpg --batch --gen-key <<'KEY'
%no-protection
Key-Type: RSA
Key-Length: 3072
Name-Real: rws CI test
Name-Email: ci@example.invalid
Expire-Date: 1d
%commit
KEY
echo "GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr/ {print $10; exit}')" >> "$GITHUB_ENV"
- name: Package (as the release does)
run: |
version=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name=="rust-web-server") | .version')
gpg --batch --armor --export-secret-keys "$GPG_KEY_ID" > "$RUNNER_TEMP/signing.asc"
RPM_SIGNING_KEY_FILE="$RUNNER_TEMP/signing.asc" \
packaging/build-packages.sh "$version" amd64 target/x86_64-unknown-linux-musl/release/rws packages
ls -l packages
- name: Repositories (as the release does)
run: |
sudo apt-get install -y apt-utils createrepo-c
packaging/build-repos.sh packages site http://localhost:8000
nohup setsid python3 -m http.server 8000 --directory site >/dev/null 2>&1 &
sleep 1 && curl -sSf localhost:8000/apt/dists/stable/InRelease | head -3
- name: deb on the runner (systemd)
run: |
sudo apt-get install -y ./packages/rws_*_amd64.deb
systemctl is-active rws
for i in $(seq 1 20); do curl -sf localhost:7878/healthz && break; sleep 1; done
curl -sSf localhost:7878/ | grep 'rws is running'
test "$(stat -c %U /etc/rws/rws.config.toml)" = root
systemd-analyze security rws.service | tail -1
sudo systemctl reload rws && sleep 1 && systemctl is-active rws
sudo apt-get install -y --reinstall ./packages/rws_*_amd64.deb && systemctl is-active rws
# An upgrade keeps a service the admin disabled disabled.
sudo systemctl disable --now rws
sudo apt-get install -y --reinstall ./packages/rws_*_amd64.deb
! systemctl is-active rws
sudo systemctl enable --now rws
sudo apt-get remove -y rws
! systemctl is-active rws
test -f /etc/rws/rws.config.toml # remove keeps config; purge deletes it
- name: deb from the apt repository
run: |
curl -sSf localhost:8000/apt/rws.gpg | sudo tee /usr/share/keyrings/rws.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/rws.gpg] http://localhost:8000/apt stable main" | sudo tee /etc/apt/sources.list.d/rws.list
sudo apt-get update -o Dir::Etc::sourcelist=/etc/apt/sources.list.d/rws.list -o Dir::Etc::sourceparts=-
sudo apt-get install -y rws
systemctl is-active rws
sudo apt-get purge -y rws
- name: rpm in a Fedora container (systemd)
run: |
docker run -d --name fedora --privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw \
--network host -v "$PWD/packages:/dist:ro" fedora:42 sh -c 'dnf install -y -q systemd curl && exec /usr/lib/systemd/systemd'
for i in $(seq 1 120); do docker exec fedora systemctl is-system-running 2>/dev/null | grep -qE 'running|degraded' && break; sleep 2; done
docker exec fedora sh -c 'rpm --import http://localhost:8000/rpm/rws.asc && rpm -K /dist/*.x86_64.rpm'
docker exec fedora dnf install -y "/dist/$(basename packages/rws-*.x86_64.rpm)"
docker exec fedora systemctl is-active rws
docker exec fedora sh -c 'for i in $(seq 1 20); do curl -sf localhost:7878/healthz && break; sleep 1; done'
docker exec fedora sh -c 'curl -sSf localhost:7878/ | grep "rws is running"'
docker exec fedora dnf remove -y rws
! docker exec fedora systemctl is-active rws
# From the signed repository (gpgcheck and repo_gpgcheck on):
docker exec fedora curl -sSf -o /etc/yum.repos.d/rws.repo http://localhost:8000/rpm/rws.repo
docker exec fedora dnf install -y rws
docker exec fedora systemctl is-active rws
- name: Diagnostics
if: failure()
run: |
sudo journalctl -u rws --no-pager | tail -50 || true
docker exec fedora journalctl -u rws --no-pager | tail -50 || true
- uses: actions/upload-artifact@v4
with:
name: packages
path: packages/*
windows-service:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: ilammy/setup-nasm@v1
- uses: Swatinem/rust-cache@v2
with:
key: windows-service
- run: cargo build --release --bin rws --features "acme auth sso mimalloc wasm-plugins storage-s3 pkcs11"
- name: Install, start, serve, stop
shell: pwsh
run: |
$site = Join-Path $env:RUNNER_TEMP "rws-site"
New-Item -ItemType Directory -Force $site | Out-Null
Set-Content (Join-Path $site "index.html") "rws service is running"
$exe = (Resolve-Path target\release\rws.exe).Path
New-Service -Name rws -BinaryPathName "`"$exe`" --windows-service=`"$site`"" -StartupType Manual | Out-Null
Start-Service rws
$body = $null
for ($i = 0; $i -lt 30; $i++) {
try { $body = (Invoke-WebRequest http://localhost:7878/ -UseBasicParsing).Content; break } catch { Start-Sleep 1 }
}
if ($body -notmatch "rws service is running") { throw "unexpected response: $body" }
(Invoke-WebRequest http://localhost:7878/healthz -UseBasicParsing).StatusCode
Stop-Service rws
(Get-Service rws).WaitForStatus("Stopped", "00:00:30")
sc.exe delete rws
- name: Diagnostics
if: failure()
shell: pwsh
run: |
Get-Service rws -ErrorAction SilentlyContinue | Format-List *
Get-WinEvent -LogName System -MaxEvents 20 | Where-Object ProviderName -eq "Service Control Manager" | Format-List TimeCreated, Message
winget:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Generate
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
version=$(gh release view --repo "$GITHUB_REPOSITORY" --json tagName -q .tagName)
echo "MANIFEST=$(packaging/winget/generate.sh "$version" "$RUNNER_TEMP/winget")" >> "$GITHUB_ENV"
- name: Validate and install
shell: pwsh
run: |
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
Install-PackageProvider -Name NuGet -Force | Out-Null
Install-Module Microsoft.WinGet.Client -Force -Repository PSGallery | Out-Null
Repair-WinGetPackageManager -AllUsers
}
winget --version
winget validate --manifest $env:MANIFEST
winget settings --enable LocalManifestFiles
winget install --manifest $env:MANIFEST --accept-source-agreements --accept-package-agreements --disable-interactivity
$rws = Join-Path $env:LOCALAPPDATA "Microsoft\WinGet\Links\rws.exe"
& $rws --version
nix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v31.11.1
with:
nix_path: nixpkgs=channel:nixos-unstable
- run: nix-build packaging/nix/ci.nix
- run: ./result/bin/rws --version