build: package and publish sync server releases
This commit is contained in:
parent
2ea29cb503
commit
8da7f10c6b
|
|
@ -13,3 +13,4 @@ server-data/
|
||||||
# OS
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
release/
|
||||||
|
|
|
||||||
23
README.md
23
README.md
|
|
@ -24,6 +24,29 @@ This server provides synchronization between devices running Verstak2. It handle
|
||||||
./build/bin/verstak-sync-server --admin-user admin --admin-pass secret
|
./build/bin/verstak-sync-server --admin-user admin --admin-pass secret
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Release packages
|
||||||
|
|
||||||
|
Build a Linux amd64 archive locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/release.sh v0.1.0-alpha.1
|
||||||
|
```
|
||||||
|
|
||||||
|
It runs the server build and tests, then writes
|
||||||
|
`release/verstak-sync-server-linux-amd64-<version>.tar.gz` and `SHA256SUMS`.
|
||||||
|
The archive contains the server binary, systemd service file and install
|
||||||
|
script.
|
||||||
|
|
||||||
|
Publish those same assets to GitHub Releases:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/publish-github-release.sh v0.1.0-alpha.1
|
||||||
|
```
|
||||||
|
|
||||||
|
The publisher requires an authenticated [`gh`](https://cli.github.com/) CLI
|
||||||
|
and a clean local `main` equal to `origin/main`. It creates and pushes an
|
||||||
|
annotated tag when necessary, then creates or updates the GitHub Release.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
| Flag | Default | Description |
|
| Flag | Default | Description |
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
VERSION="${1:-}"
|
||||||
|
REPOSITORY="mirivlad/verstak-sync-server"
|
||||||
|
RELEASE_SCRIPT="${VERSTAK_RELEASE_SCRIPT:-$ROOT/scripts/release.sh}"
|
||||||
|
RELEASE_DIR="${VERSTAK_RELEASE_DIR:-$ROOT/release}"
|
||||||
|
GIT_BIN="${GIT_BIN:-git}"
|
||||||
|
GH_BIN="${GH_BIN:-gh}"
|
||||||
|
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
|
||||||
|
echo "usage: $0 <version>" >&2
|
||||||
|
echo "example: $0 v0.1.0-alpha.1" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! command -v "$GH_BIN" >/dev/null; then
|
||||||
|
echo "gh CLI is required to publish a GitHub Release" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$("$GIT_BIN" branch --show-current)" != "main" ]]; then
|
||||||
|
echo "GitHub releases must be published from main" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -n "$("$GIT_BIN" status --porcelain)" ]]; then
|
||||||
|
echo "working tree must be clean before publishing a release" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$GH_BIN" auth status
|
||||||
|
"$GIT_BIN" fetch origin main --tags
|
||||||
|
HEAD="$("$GIT_BIN" rev-parse HEAD)"
|
||||||
|
if [[ "$HEAD" != "$("$GIT_BIN" rev-parse origin/main)" ]]; then
|
||||||
|
echo "local main must match origin/main before publishing a release" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$RELEASE_SCRIPT" "$VERSION"
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
ASSETS=("$RELEASE_DIR"/*.tar.gz "$RELEASE_DIR"/*.tgz)
|
||||||
|
if [[ -f "$RELEASE_DIR/SHA256SUMS" ]]; then
|
||||||
|
ASSETS+=("$RELEASE_DIR/SHA256SUMS")
|
||||||
|
fi
|
||||||
|
if [[ ${#ASSETS[@]} -eq 0 ]]; then
|
||||||
|
echo "no release assets found in $RELEASE_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$GIT_BIN" rev-parse -q --verify "refs/tags/$VERSION" >/dev/null; then
|
||||||
|
if [[ "$("$GIT_BIN" rev-parse "${VERSION}^{commit}")" != "$HEAD" ]]; then
|
||||||
|
echo "existing tag $VERSION does not point at HEAD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
"$GIT_BIN" tag -a "$VERSION" -m "Release $VERSION"
|
||||||
|
"$GIT_BIN" push origin "refs/tags/$VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$GH_BIN" release view "$VERSION" --repo "$REPOSITORY" >/dev/null 2>&1; then
|
||||||
|
"$GH_BIN" release upload "$VERSION" "${ASSETS[@]}" --repo "$REPOSITORY" --clobber
|
||||||
|
else
|
||||||
|
"$GH_BIN" release create "$VERSION" "${ASSETS[@]}" \
|
||||||
|
--repo "$REPOSITORY" \
|
||||||
|
--title "Verstak Sync Server $VERSION" \
|
||||||
|
--generate-notes \
|
||||||
|
--latest \
|
||||||
|
--verify-tag
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "GitHub release:"
|
||||||
|
"$GH_BIN" release view "$VERSION" --repo "$REPOSITORY" --json url --jq .url
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
VERSION="${1:-}"
|
||||||
|
|
||||||
|
if [[ -z "$VERSION" || ! "$VERSION" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then
|
||||||
|
echo "usage: $0 <version>" >&2
|
||||||
|
echo "example: $0 v0.1.0-alpha.1" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ "$(go env GOOS)" != "linux" || "$(go env GOARCH)" != "amd64" ]]; then
|
||||||
|
echo "sync-server release artifacts are currently built for linux/amd64" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== verstak sync server release $VERSION ==="
|
||||||
|
"$ROOT/scripts/build.sh"
|
||||||
|
|
||||||
|
RELEASE_ROOT="$ROOT/release"
|
||||||
|
STAGING="$RELEASE_ROOT/verstak-sync-server-$VERSION-linux-amd64"
|
||||||
|
ARCHIVE="$RELEASE_ROOT/verstak-sync-server-linux-amd64-$VERSION.tar.gz"
|
||||||
|
rm -rf "$STAGING" "$ARCHIVE"
|
||||||
|
mkdir -p "$STAGING/scripts"
|
||||||
|
|
||||||
|
cp "$ROOT/build/bin/verstak-sync-server" "$STAGING/verstak-sync-server"
|
||||||
|
cp "$ROOT/README.md" "$ROOT/LICENSE" "$ROOT/verstak-server.service" "$STAGING/"
|
||||||
|
cp "$ROOT/scripts/install.sh" "$STAGING/scripts/install.sh"
|
||||||
|
tar -C "$RELEASE_ROOT" -czf "$ARCHIVE" "$(basename "$STAGING")"
|
||||||
|
(cd "$RELEASE_ROOT" && sha256sum "$(basename "$ARCHIVE")" > SHA256SUMS)
|
||||||
|
|
||||||
|
echo "release archive: $ARCHIVE"
|
||||||
|
echo "checksums: $RELEASE_ROOT/SHA256SUMS"
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
PUBLISHER="$ROOT/scripts/publish-github-release.sh"
|
||||||
|
VERSION="v0.0.0-test"
|
||||||
|
REPOSITORY="mirivlad/verstak-sync-server"
|
||||||
|
ASSET_NAME="verstak-sync-server-linux-amd64-${VERSION}.tar.gz"
|
||||||
|
WORK="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$WORK"' EXIT
|
||||||
|
|
||||||
|
if [[ ! -x "$PUBLISHER" ]]; then
|
||||||
|
echo "publisher is missing or not executable: $PUBLISHER" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$WORK/bin" "$WORK/release" "$WORK/state"
|
||||||
|
LOG="$WORK/log"
|
||||||
|
export LOG
|
||||||
|
|
||||||
|
cat > "$WORK/release.sh" <<'SCRIPT'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
printf 'release:%s\n' "$1" >> "$LOG"
|
||||||
|
printf 'archive\n' > "$VERSTAK_RELEASE_DIR/verstak-sync-server-linux-amd64-$1.tar.gz"
|
||||||
|
printf 'checksum\n' > "$VERSTAK_RELEASE_DIR/SHA256SUMS"
|
||||||
|
SCRIPT
|
||||||
|
chmod +x "$WORK/release.sh"
|
||||||
|
|
||||||
|
cat > "$WORK/bin/git" <<'SCRIPT'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ "$PWD" != "${EXPECTED_ROOT:?}" ]]; then
|
||||||
|
echo "publisher did not enter repository root: $PWD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
case "${1:-}" in
|
||||||
|
status) exit 0 ;;
|
||||||
|
branch) echo main ;;
|
||||||
|
fetch) printf 'fetch\n' >> "$LOG" ;;
|
||||||
|
rev-parse)
|
||||||
|
if [[ "${2:-}" == "-q" ]]; then
|
||||||
|
if [[ -f "$TEST_STATE/tag" ]]; then echo test-commit; exit 0; fi
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo test-commit
|
||||||
|
;;
|
||||||
|
tag) touch "$TEST_STATE/tag"; printf 'tag:%s\n' "${3:-}" >> "$LOG" ;;
|
||||||
|
push) printf 'push:%s:%s\n' "${2:-}" "${3:-}" >> "$LOG" ;;
|
||||||
|
*) echo "unexpected git invocation: $*" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
SCRIPT
|
||||||
|
chmod +x "$WORK/bin/git"
|
||||||
|
|
||||||
|
cat > "$WORK/bin/gh" <<'SCRIPT'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
case "${1:-}:${2:-}" in
|
||||||
|
auth:status) printf 'auth\n' >> "$LOG" ;;
|
||||||
|
release:view)
|
||||||
|
if [[ -f "$TEST_STATE/release" ]]; then echo https://github.example/release; else exit 1; fi
|
||||||
|
;;
|
||||||
|
release:create) touch "$TEST_STATE/release"; printf 'create:%s\n' "$*" >> "$LOG" ;;
|
||||||
|
release:upload) printf 'upload:%s\n' "$*" >> "$LOG" ;;
|
||||||
|
*) echo "unexpected gh invocation: $*" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
SCRIPT
|
||||||
|
chmod +x "$WORK/bin/gh"
|
||||||
|
|
||||||
|
run_publisher() {
|
||||||
|
VERSTAK_RELEASE_SCRIPT="$WORK/release.sh" \
|
||||||
|
VERSTAK_RELEASE_DIR="$WORK/release" \
|
||||||
|
GIT_BIN="$WORK/bin/git" \
|
||||||
|
GH_BIN="$WORK/bin/gh" \
|
||||||
|
EXPECTED_ROOT="$ROOT" \
|
||||||
|
TEST_STATE="$WORK/state" \
|
||||||
|
"$PUBLISHER" "$VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_publisher
|
||||||
|
grep -Fqx "release:$VERSION" "$LOG"
|
||||||
|
grep -Fqx "tag:$VERSION" "$LOG"
|
||||||
|
grep -Fqx "push:origin:refs/tags/$VERSION" "$LOG"
|
||||||
|
grep -F "release create $VERSION" "$LOG" >/dev/null
|
||||||
|
grep -F "$ASSET_NAME" "$LOG" >/dev/null
|
||||||
|
grep -F "SHA256SUMS" "$LOG" >/dev/null
|
||||||
|
|
||||||
|
run_publisher
|
||||||
|
grep -F "release upload $VERSION" "$LOG" >/dev/null
|
||||||
|
|
||||||
|
echo "GitHub release publisher test passed"
|
||||||
Loading…
Reference in New Issue