Update Repository #417
This file contains 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: Update Repository | |
# Controls when the workflow will run | |
on: | |
#push: | |
# If the configuration has changed, this ensures we apply updates. | |
#branches: [ main ] | |
schedule: | |
# Upstream releases around once per month, so twice a week should be fine. | |
- cron: '23 14 * * mon,thu' | |
workflow_dispatch: | |
jobs: | |
check-upstream: | |
name: Check for a new releases upstream | |
runs-on: ubuntu-latest | |
outputs: | |
innernet_release: ${{ steps.check-latest-release.outputs.innernet_release }} | |
innernet_version: ${{ steps.check-latest-release.outputs.innernet_version }} | |
tarball_url: ${{ steps.check-latest-release.outputs.tarball_url }} | |
new_release_exists: ${{ steps.check-repo-release.outputs.new_release_exists }} | |
steps: | |
- name: Install Distro Dependencies | |
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes jq liblzma-dev reprepro | |
- name: Set Ubuntu Release Name | |
id: set-ubuntu-release-name | |
run: | | |
echo "ubuntu_release=$(lsb_release --short --codename)" >>"$GITHUB_OUTPUT" | |
- name: Check Latest Release | |
id: check-latest-release | |
run: | | |
wget -O- \ | |
-H'Accept: application/json' \ | |
"https://api.github.com/repos/tonarino/innernet/releases/latest" \ | |
| jq -r '(.name + " " + .tarball_url)' \ | |
| ( | |
read release tarball_url | |
echo "innernet_release=$release" >>"$GITHUB_OUTPUT" | |
echo "innernet_version=${release#v}" >>"$GITHUB_OUTPUT" | |
echo "tarball_url=$tarball_url" >>"$GITHUB_OUTPUT" | |
echo "Latest release: $release" | |
) | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
# See https://github.com/marketplace/actions/github-push | |
persist-credentials: false | |
fetch-depth: 0 | |
- name: Check Repo Release | |
id: check-repo-release | |
run: | | |
declare -a new_release_exists | |
ver_codenames=( $(python3 -c 'import json; import yaml; import sys; json.dump(yaml.safe_load(open(sys.argv[1])), sys.stdout)' .github/workflows/main.yml | jq -r '.jobs."build-deb".strategy.matrix.include[] | .os+"/"+.codename') ) | |
for arch in amd64 armhf arm64; do | |
for ver_codename in "${ver_codenames[@]}"; do | |
ver=${ver_codename%/*} | |
codename=${ver_codename##*/} | |
# Note the leading v to match the Git tag. | |
indexed=v$(reprepro -A "$arch" -b debian --list-format '${version}\n' listmatched "$codename" innernet) | |
upstream="${{ steps.check-latest-release.outputs.innernet_release }}-0ubuntu0~$codename" | |
echo "Repo release in $codename/$arch: $indexed" | |
if [ "x$indexed" != "x$upstream" ]; then | |
new_release_exists+=( "\"$ver\"" ) | |
fi | |
done | |
done | |
(IFS=$'\n' ; echo "new_release_exists=[$(echo -n "${new_release_exists[*]}" | sort -u | tr '\n' , | sed -e 's;,$;;')]" >>"$GITHUB_OUTPUT") | |
- name: Show Output | |
id: show-output | |
run: | | |
echo "## Job Outputs" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`innernet_release=${{ steps.check-latest-release.outputs.innernet_release }}\`" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`innernet_version=${{ steps.check-latest-release.outputs.innernet_version }}\`" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`tarball_url=${{ steps.check-latest-release.outputs.tarball_url }}\`" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`new_release_exists=${{ steps.check-repo-release.outputs.new_release_exists }}\`" >>"$GITHUB_STEP_SUMMARY" | |
build-deb: | |
name: Build DEB Packages ${{ matrix.os }}/${{ matrix.arch }} | |
needs: [check-upstream] | |
if: "fromJson(needs.check-upstream.outputs.new_release_exists)[0] != null" | |
runs-on: ubuntu-latest | |
container: | |
image: ${{ matrix.image }} | |
strategy: | |
matrix: | |
arch: [amd64] | |
os: ${{ fromJson(needs.check-upstream.outputs.new_release_exists) }} | |
include: | |
- os: ubuntu-24.04 | |
codename: noble | |
image: ubuntu:24.04 | |
- os: ubuntu-22.04 | |
codename: jammy | |
image: ubuntu:22.04 | |
- os: ubuntu-20.04 | |
codename: focal | |
image: ubuntu:20.04 | |
steps: | |
- name: Install Distro Dependencies | |
run: | | |
apt-get update | |
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes build-essential ca-certificates dpkg-dev liblzma-dev wget | |
- name: Download Latest Release | |
id: download-release | |
run: | | |
wget -O- "${{ needs.check-upstream.outputs.tarball_url }}" | tar xz | |
mv tonarino-innernet-*/* . | |
rm -fr tonarino-innernet-* | |
sed -i -e '/^readme =/ d' server/Cargo.toml | |
- name: Install Rust | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable | |
profile: minimal | |
override: true | |
- name: Install cargo-deb | |
run: | | |
type -p cargo-deb >/dev/null || cargo install cargo-deb | |
- name: Set Up Rust Cache | |
uses: Swatinem/rust-cache@v2 | |
with: | |
key: ${{ matrix.os }}-amd64 | |
- name: Build Client DEB | |
run: cargo deb -p client --deb-version=${{ needs.check-upstream.outputs.innernet_version }}-0ubuntu0~${{ matrix.codename }} | |
- name: Build Server DEB | |
run: cargo deb -p server --deb-version=${{ needs.check-upstream.outputs.innernet_version }}-0ubuntu0~${{ matrix.codename }} | |
- name: Upload DEBs | |
uses: actions/upload-artifact@v4 | |
with: | |
# Syntax: https://github.com/actions/upload-artifact/issues/22 | |
name: deb ${{ matrix.codename }} ${{ matrix.arch }} | |
path: target/debian/*.deb | |
build-cross-deb: | |
name: Build DEB Packages ${{ matrix.os }}/${{ matrix.arch }} (Cross-Compiled) | |
needs: [check-upstream] | |
if: "fromJson(needs.check-upstream.outputs.new_release_exists)[0] != null" | |
runs-on: ${{ matrix.os }} | |
strategy: | |
matrix: | |
os: ${{ fromJson(needs.check-upstream.outputs.new_release_exists) }} | |
arch: | |
- armhf | |
- arm64 | |
include: | |
- arch: armhf | |
target: armv7-unknown-linux-gnueabihf | |
target_prefix: arm-linux-gnueabihf- | |
- arch: arm64 | |
target: aarch64-unknown-linux-gnu | |
target_prefix: aarch64-linux-gnu- | |
steps: | |
- name: Infer Configuration | |
id: config | |
run: | | |
case "${{ matrix.os }}" in | |
ubuntu-22.04) | |
echo "codename=jammy" >>"$GITHUB_OUTPUT" | |
;; | |
ubuntu-20.04) | |
echo "codename=focal" >>"$GITHUB_OUTPUT" | |
;; | |
*) | |
if [ "ubuntu-$(lsb_release -sr)" = "${{ matrix.os }}" ]; then | |
echo "codename=$(lsb_release -sc)" >>"$GITHUB_OUTPUT" | |
else | |
echo "unknown matrix.os: ${{ matrix.os }}" >&2 | |
exit 1 | |
fi | |
;; | |
esac | |
- name: Install Distro Dependencies | |
run: | | |
sudo sed -i -e 's;^\(deb\(-src\)\?\)\(\s\+\)\(\(https\?://azure\.archive\.ubuntu\.com\|https\?://archive\.ubuntu\.com\|https\?://security\.ubuntu\.com\)/\|mirror+file:/etc/apt/apt-mirrors\.txt\);\1\3[arch=amd64,i386]\3\4;' /etc/apt/sources.list /etc/apt/sources.list.d/*.list | |
for f in /etc/apt/sources.list.d/*.sources; do | |
# -i inplace doesn't work with END. | |
sudo awk 'BEGIN { FS = ": +"; } END { if (found) print "Architectures: amd64 i386" archs; } found && !$0 { print "Architectures: amd64 i386" archs; } !$0 { found = 0; archs = ""; } $1 == "URIs" && $2 ~ /azure\.archive\.ubuntu\.com/ { found = 1; } $1 == "Architectures" { archs = " " $2; next; } { print; }' "$f" | sudo tee "$f.tmp" >/dev/null | |
sudo mv "$f.tmp" "$f" | |
done | |
sudo dpkg --add-architecture "${{ matrix.arch }}" | |
# apt-get install goes into an infinite loop (use -o Debug::pkgAcquire=true to see it) if we use apt-mirrors.txt, like GitHub does for the host architecture. | |
# So we just limit the mirrors file and use our trusty sources.list overrides. | |
echo "deb [arch=armhf,arm64,riscv64] http://ports.ubuntu.com/ ${{ steps.config.outputs.codename }} main universe" | sudo tee /etc/apt/sources.list.d/ports.list >/dev/null | |
echo "deb [arch=armhf,arm64,riscv64] http://ports.ubuntu.com/ ${{ steps.config.outputs.codename }}-security main universe" | sudo tee -a /etc/apt/sources.list.d/ports.list >/dev/null | |
echo "deb [arch=armhf,arm64,riscv64] http://ports.ubuntu.com/ ${{ steps.config.outputs.codename }}-updates main universe" | sudo tee -a /etc/apt/sources.list.d/ports.list >/dev/null | |
sudo apt-get update | |
sudo env DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes dpkg-dev liblzma-dev pkg-config build-essential "crossbuild-essential-${{ matrix.arch }}" libsqlite3-dev:"${{ matrix.arch }}" | |
- name: Set Up Environment | |
id: setup-env | |
run: | | |
echo "CC_${{ matrix.target }}=${{ matrix.target_prefix }}gcc" >>"$GITHUB_ENV" | |
echo "HOST_CC=gcc" >>"$GITHUB_ENV" | |
mkdir -p .cargo | |
echo "[target.${{ matrix.target }}]" >>.cargo/config | |
echo "linker = \"${{ matrix.target_prefix }}gcc\"" >>.cargo/config | |
echo "strip = { path = \"${{ matrix.target_prefix }}strip\" }" >>.cargo/config | |
echo "objcopy = { path = \"${{ matrix.target_prefix }}objcopy\" }" >>.cargo/config | |
- name: Download Latest Release | |
id: download-release | |
run: | | |
wget -O- "${{ needs.check-upstream.outputs.tarball_url }}" | tar xz | |
mv tonarino-innernet-*/* . | |
rm -fr tonarino-innernet-* | |
sed -i -e '/^readme =/ d' server/Cargo.toml | |
- name: Install Rust | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable | |
profile: minimal | |
override: true | |
target: ${{ matrix.target }} | |
- name: Set Up Rust Cache | |
uses: Swatinem/rust-cache@v2 | |
with: | |
key: ${{ matrix.os }}-${{ matrix.arch }} | |
- name: Install cargo-deb | |
run: | | |
type -p cargo-deb >/dev/null || cargo install cargo-deb | |
- name: Build Client DEB | |
run: | | |
cargo deb -p client --target=${{ matrix.target }} --deb-version=${{ needs.check-upstream.outputs.innernet_version }}-0ubuntu0~${{ steps.config.outputs.codename }} | |
- name: Build Server DEB | |
run: | | |
cargo deb -p server --target=${{ matrix.target }} --deb-version=${{ needs.check-upstream.outputs.innernet_version }}-0ubuntu0~${{ steps.config.outputs.codename }} | |
- name: Upload DEBs | |
uses: actions/upload-artifact@v4 | |
with: | |
# Syntax: https://github.com/actions/upload-artifact/issues/22 | |
name: deb ${{ steps.config.outputs.codename }} ${{ matrix.arch }} | |
path: target/${{ matrix.target }}/debian/*.deb | |
test-cross: | |
name: Test DEB Packages ${{ matrix.image }}/${{ matrix.os }} (QEMU) | |
needs: [check-upstream, build-cross-deb] | |
if: "fromJson(needs.check-upstream.outputs.new_release_exists)[0] != null" | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
image: | |
- raspios_lite:latest | |
- raspios_lite_arm64:latest | |
include: | |
- image: raspios_lite:latest | |
os: ubuntu-22.04 | |
codename: jammy | |
qemu_cpu: cortex-a7 | |
qemu_cpu_info: cpuinfo/raspberrypi_3b | |
arch: armhf | |
- image: raspios_lite_arm64:latest | |
os: ubuntu-22.04 | |
codename: jammy | |
qemu_cpu: cortex-a53 | |
qemu_cpu_info: cpuinfo/raspberrypi_4b | |
arch: arm64 | |
steps: | |
- name: Download DEBs | |
if: "contains(needs.check-upstream.outputs.new_release_exists, matrix.os)" | |
uses: actions/download-artifact@v4 | |
with: | |
name: deb ${{ matrix.codename }} ${{ matrix.arch }} | |
path: ./artifacts | |
- name: Test DEBs | |
id: test | |
if: "contains(needs.check-upstream.outputs.new_release_exists, matrix.os)" | |
uses: pguyot/arm-runner-action@v2 | |
with: | |
base_image: ${{ matrix.image }} | |
cpu: ${{ matrix.qemu_cpu }} | |
cpu_info: ${{ matrix.qemu_cpu_info }} | |
copy_artifact_path: github_test_summary | |
debug: false | |
commands: | | |
echo "* \`arch=$(dpkg-architecture -q DEB_HOST_ARCH)\`" >>"github_test_summary" | |
echo "* \`codename=$(lsb_release --short --codename)\`" >>"github_test_summary" | |
dpkg -i artifacts/innernet_*.deb | |
dpkg -i artifacts/innernet-server_*.deb | |
DEBIAN_FRONTEND=noninteractive apt-get update | |
DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends --yes --fix-broken install | |
innernet --version | |
innernet-server --version | |
- name: Show Output | |
id: show-output | |
if: "contains(needs.check-upstream.outputs.new_release_exists, matrix.os)" | |
run: | | |
echo "## Job Outputs" >>"$GITHUB_STEP_SUMMARY" | |
cat github_test_summary >>"$GITHUB_STEP_SUMMARY" | |
update-repo: | |
name: Update Repository | |
needs: [check-upstream, build-deb, test-cross] | |
if: "fromJson(needs.check-upstream.outputs.new_release_exists)[0] != null" | |
runs-on: ubuntu-latest | |
steps: | |
- name: Install Distro Dependencies | |
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes git gpg reprepro | |
- name: Set Up GPG Keys | |
run: | | |
mkdir -p -m 0700 "$HOME/.gnupg" | |
echo 'pinentry-mode loopback' >>"$HOME/.gnupg/gpg.conf" | |
echo 'allow-loopback-pinentry' >>"$HOME/.gnupg/gpg-agent.conf" | |
echo 'allow-preset-passphrase' >>"$HOME/.gnupg/gpg-agent.conf" | |
gpgconf --reload gpg-agent | |
echo "${{ secrets.GPG_SIGNING_KEY }}" | gpg --quiet --batch --yes --import | |
echo '${{ secrets.GPG_SIGNING_PASSPHRASE }}' | /usr/lib/gnupg/gpg-preset-passphrase --preset 57F0E65446A301CC19914FD61167922350A2D8B2 | |
- name: Checkout | |
uses: actions/checkout@v4 | |
with: | |
# See https://github.com/marketplace/actions/github-push | |
persist-credentials: false | |
fetch-depth: 0 | |
- name: Download DEBs | |
uses: actions/download-artifact@v4 | |
with: | |
path: ./artifacts | |
- name: Include DEBs | |
id: include-debs | |
run: | | |
declare -a codenames archs | |
for path in artifacts/deb\ */*.deb; do | |
codename=${path#artifacts/deb } | |
arch=${codename##* } | |
arch=${arch%%/*} | |
codename=${codename% *} | |
name="$(dpkg-deb --field "$path" package)" | |
if [ ! -e "debian/pool/contrib/i/$name/$(basename "$path")" ]; then | |
reprepro -A "$arch" --export=silent-never -b debian includedeb "$codename" "$path" | |
codenames+=( "$codename" ) | |
archs+=( "$arch" ) | |
else | |
echo 'Package $name already exists. Silently ignored.' | |
fi | |
done | |
(IFS=$'\n' ; echo "codenames=$(echo "${codenames[*]}" | sort -u | xargs -r)" >>"$GITHUB_OUTPUT") | |
(IFS=$'\n' ; echo "archs=$(echo "${archs[*]}" | sort -u | xargs -r)" >>"$GITHUB_OUTPUT") | |
- name: Update Repository | |
run: | | |
has_changes() { | |
git status --porcelain "$@" | grep -q . | |
} | |
if has_changes debian/pool; then | |
reprepro -b debian export | |
fi | |
if has_changes debian/{db,dists,pool}; then | |
git add debian/{db,dists,pool} | |
git \ | |
-c 'user.email=41898282+github-actions[bot]@users.noreply.github.com' \ | |
-c 'user.name=github-actions[bot]' \ | |
commit -m "Included release tonarino/innernet@${{ needs.check-upstream.outputs.innernet_release }} in ${{ steps.include-debs.outputs.codenames }} for ${{ steps.include-debs.outputs.archs }}." | |
else | |
echo 'No updates to commit.' | |
fi | |
- name: Push changes | |
uses: ad-m/github-push-action@master | |
if: github.ref_name == 'main' | |
with: | |
github_token: ${{ secrets.GITHUB_TOKEN }} | |
branch: ${{ github.ref }} | |
- name: Show Output | |
id: show-output | |
run: | | |
echo "## Job Outputs" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`codenames=${{ steps.include-debs.outputs.codenames }}\`" >>"$GITHUB_STEP_SUMMARY" | |
echo "* \`archs=${{ steps.include-debs.outputs.archs }}\`" >>"$GITHUB_STEP_SUMMARY" |