probe: add native OpenWrt deployment and signed automatic updates [CI]
This commit is contained in:
1 parent
24ba05fbb6
commit
cd193378a6
26 files changed
+987
-9
No files matched your search
@@ -183,6 +183,20 @@ for tag in "$image_version-$arch"; do
|
||||
echo "pushed development image $repository:$tag"
|
||||
done
|
||||
|
||||
# Reuse the static Probe/enrollment binaries already built above; do not compile again.
|
||||
# Publish before the multi-arch image offer wakes online native nodes.
|
||||
if [[ "$component" == probe ]]; then
|
||||
buildah rm "moshiro-openwrt-extract-$arch" >/dev/null 2>&1 || true
|
||||
native_container="$(buildah from --arch "$arch" --name "moshiro-openwrt-extract-$arch" "$local_image")"
|
||||
native_dir="$work/openwrt"
|
||||
mkdir -p "$native_dir"
|
||||
native_mount="$(buildah mount "$native_container")"
|
||||
cp "$native_mount/usr/local/bin/moshiro-probe" "$native_mount/usr/local/bin/fleet-enroll" "$native_dir/"
|
||||
buildah unmount "$native_container" >/dev/null
|
||||
buildah rm "$native_container" >/dev/null
|
||||
bash "$root/ci/publish-openwrt.sh" dev "$node_rid" "$native_dir"
|
||||
fi
|
||||
|
||||
# Agent and Probe manifests are signed after both architecture-specific images
|
||||
# have been pushed. Backend is still a single-architecture development image.
|
||||
if [[ "$component" == backend && -n "${RELEASE_SIGNING_KEY:-}" ]]; then
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env bash
|
||||
# Package an already-built native Probe 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-probe" "$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-probe.init" "$work/stage/probe.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="probe-$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='probe', 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 Probe $version ($channel/$rid)"
|
||||
@@ -70,6 +70,11 @@ build_arch_image() {
|
||||
install -m 0755 "$work/fleet-enroll" "$context/app/fleet-enroll"
|
||||
install -m 0755 "$work/moshiro-$component" "$context/app/moshiro-$component"
|
||||
install -m 0644 "$work"/lib*.so.* "$context/app/"
|
||||
if [[ "$component" == probe && -n "${RELEASE_SIGNING_KEY:-}" && "$version" != *-* ]]; then
|
||||
native_rid=linux-musl-x64
|
||||
[[ "$arch" != arm64 ]] || native_rid=linux-musl-arm64
|
||||
bash "$root/ci/publish-openwrt.sh" release "$native_rid" "$context/app"
|
||||
fi
|
||||
: > "$context/config/.keep"
|
||||
install -m 0755 "$root/packaging/container/entrypoint.sh" "$context/entrypoint.sh"
|
||||
|
||||
|
||||
Reference in new issue
Block a user