Remove Probe build jobs and release paths. Transfer Gitea publishing credentials to both Agent architecture jobs, publish each platform archive once, and run slow tests after development images are published.
69 lines
4.1 KiB
Bash
69 lines
4.1 KiB
Bash
#!/usr/bin/env bash
|
|
# Package an already-built native Agent and publish an independently signed feed.
|
|
# Used after verify/web-build gates for dev, and after all release builds for tags.
|
|
set -euo pipefail
|
|
channel="${1:?usage: publish-openwrt.sh <dev|release> <rid> <binary-directory>}"
|
|
rid="${2:?}"; source_dir="${3:?}"
|
|
[[ "$channel" == dev || "$channel" == release ]] || exit 2
|
|
[[ "$rid" == linux-musl-arm64 || "$rid" == linux-musl-x64 ]] || exit 2
|
|
if [[ "$channel" == release ]]; then
|
|
[[ "${CI_COMMIT_TAG:-}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo 'release feed requires a stable version tag' >&2; exit 2; }
|
|
else
|
|
[[ -z "${CI_COMMIT_TAG:-}" && "${CI_PIPELINE_EVENT:-}" == push && "${CI_COMMIT_BRANCH:-}" == main && "${CI_COMMIT_MESSAGE:-}" == *'[CI]'* ]] \
|
|
|| { echo 'dev feed requires a main push with [CI]' >&2; exit 2; }
|
|
fi
|
|
[[ -n "${RELEASE_SIGNING_KEY:-}" && -n "${GITEA_TOKEN:-}" ]] || { echo 'OpenWrt publishing requires signing and Gitea secrets' >&2; exit 2; }
|
|
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
source "$root/ci/version.sh"
|
|
version="$MOSHIRO_VERSION"
|
|
work="$(mktemp -d)"
|
|
trap 'rm -rf "$work"' EXIT
|
|
mkdir "$work/stage"
|
|
install -m 755 "$source_dir/moshiro-agent" "$source_dir/fleet-enroll" "$work/stage/"
|
|
for library in "$source_dir"/lib*.so.*; do
|
|
[[ ! -f "$library" ]] || install -m 644 "$library" "$work/stage/"
|
|
done
|
|
install -m 755 "$root/packaging/openwrt/install.sh" "$work/stage/openwrt.sh"
|
|
install -m 755 "$root/packaging/openwrt/native-agent.init" "$work/stage/agent.init"
|
|
install -m 755 "$root/packaging/openwrt/updater.init" "$work/stage/updater.init"
|
|
members=()
|
|
for file in "$work/stage/"*; do members+=("$(basename "$file")"); done
|
|
tar --sort=name --owner=0 --group=0 --numeric-owner -czf "$work/package.tar.gz" -C "$work/stage" "${members[@]}"
|
|
hash="$(sha256sum "$work/package.tar.gz" | cut -d' ' -f1)"
|
|
size="$(stat -c%s "$work/package.tar.gz")"
|
|
package="agent-$rid-$hash.tar.gz"
|
|
seq="$(git -C "$root" show -s --format=%ct HEAD)"
|
|
# Commit time is stable across retries; equal timestamps intentionally do not auto-upgrade.
|
|
python3 - "$channel" "$rid" "$version" "$package" "$hash" "$size" "$seq" > "$work/manifest.json" <<'PY'
|
|
import json, sys
|
|
channel, rid, version, package, sha256, size, seq = sys.argv[1:]
|
|
print(json.dumps(dict(schema=1, component='agent', channel=channel, rid=rid,
|
|
version=version, package=package, sha256=sha256, size=int(size), seq=int(seq)), separators=(',', ':')), end='')
|
|
PY
|
|
chmod 700 "$work"
|
|
printf '%s\n' "$RELEASE_SIGNING_KEY" > "$work/key.pem"
|
|
chmod 600 "$work/key.pem"
|
|
openssl dgst -sha256 -sign "$work/key.pem" -out "$work/signature" "$work/manifest.json"
|
|
base64 -w0 "$work/signature" > "$work/manifest.sig"
|
|
base="${GITEA_BASE:-http://127.0.0.1:3100}"
|
|
base="${base%/}/api/packages/justme/generic/moshiro-openwrt"
|
|
# Credentials only in a protected curl config, never command-line arguments or output.
|
|
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" > "$work/curl.conf"
|
|
chmod 600 "$work/curl.conf"
|
|
upload() {
|
|
local path="$1" file="$2" mutable="${3:-false}" code
|
|
if [[ "$mutable" == true ]]; then
|
|
code="$(curl --silent --show-error --config "$work/curl.conf" --request DELETE --output "$work/response" --write-out '%{http_code}' "$base/$path")"
|
|
[[ "$code" == 204 || "$code" == 200 || "$code" == 404 ]] || { echo "cannot replace OpenWrt feed: HTTP $code" >&2; return 1; }
|
|
fi
|
|
code="$(curl --silent --show-error --retry 3 --config "$work/curl.conf" --upload-file "$file" --output "$work/response" --write-out '%{http_code}' "$base/$path")"
|
|
# Immutable content-addressed archives may already exist after a retry.
|
|
[[ "$code" == 2* || ( "$mutable" == false && "$code" == 409 ) ]] || { echo "OpenWrt upload failed: HTTP $code" >&2; return 1; }
|
|
}
|
|
upload "$version/$package" "$work/package.tar.gz"
|
|
# A transient manifest/signature mismatch is rejected, then retried by the device.
|
|
# Publish the channel pointer only after its immutable payload is downloadable.
|
|
upload "$channel/manifest-$rid.sig" "$work/manifest.sig" true
|
|
upload "$channel/manifest-$rid.json" "$work/manifest.json" true
|
|
echo "published signed OpenWrt Agent $version ($channel/$rid)"
|