Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/scripts/release/r2/publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ metadata = {
},
}

guard_hash = env.get("GUARD_VERSION_HASH", "")
if guard_hash:
metadata["guard"] = {"version": {"hash": guard_hash}}

if env["RELEASE_CHANNEL"] == "beta":
match = re.match(r"^v?(\d+\.\d+\.\d+)-beta\.([1-9][0-9]*)$", env["RELEASE_VERSION"])
if not match:
Expand All @@ -131,6 +135,9 @@ if env["RELEASE_CHANNEL"] == "beta":
metadata["betaNumber"] = beta_number
metadata["betaVersion"] = env["RELEASE_VERSION"]
metadata["stateSource"] = env.get("STATE_SOURCE") or "workflow input"
else:
metadata["stableVersion"] = env["RELEASE_VERSION"]
metadata["stateSource"] = env.get("STATE_SOURCE") or "workflow input"

Path(env["METADATA_PATH"]).write_text(json.dumps(metadata, indent=2) + "\n", encoding="utf-8")
PY
Expand Down
24 changes: 13 additions & 11 deletions .github/workflows/guard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,6 @@ jobs:
components: rustfmt, clippy

- name: Format
run: cargo fmt --all --check

- name: Clippy
run: cargo clippy --locked --workspace --all-targets -- -D warnings

- name: Test
run: cargo test --locked --workspace

- name: Install Flavor
if: runner.os != 'Windows'
run: |
set -euo pipefail
Expand All @@ -55,5 +46,16 @@ jobs:
& (Join-Path $env:RUNNER_TEMP 'manage-flavor.ps1') install --bin-dir $binDir
$binDir | Out-File -Append -Encoding utf8 $env:GITHUB_PATH

- name: Flavor self-check
run: flavor check --root . --config flavor.toml
- name: Guard
shell: bash
run: |
set -euo pipefail
cargo build --quiet --locked -p runseal
exe=runseal
if [ "${RUNNER_OS:-}" = "Windows" ]; then
exe=runseal.exe
fi
bin_dir="$PWD/.local/tmp/ci-guard-bin"
mkdir -p "$bin_dir"
cp "target/debug/$exe" "$bin_dir/$exe"
PATH="$bin_dir:$PWD/target/debug:$PATH" "$bin_dir/$exe" :guard
18 changes: 18 additions & 0 deletions .github/workflows/release-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ jobs:
id: beta
run: python3 .github/scripts/release/metadata/beta.py

- name: Guard version policy
shell: bash
run: |
set -euo pipefail
PATH="$PWD/target/debug:$PATH" cargo run --quiet --locked -p runseal -- :guard version-check

verify:
needs: metadata
runs-on: ubuntu-latest
Expand All @@ -73,6 +79,7 @@ jobs:
run: cargo clippy --locked --workspace --all-targets -- -D warnings

- name: Install Flavor
shell: bash
run: |
set -euo pipefail
curl -fsSL https://flavor.perish.uk/manage.sh -o "$RUNNER_TEMP/manage-flavor.sh"
Expand Down Expand Up @@ -157,6 +164,15 @@ jobs:
path: dist/${{ needs.metadata.outputs.release_version }}
merge-multiple: true

- name: Resolve guard version hash
id: guard_hash
shell: bash
run: |
set -euo pipefail
PATH="$PWD/target/debug:$PATH"
hash=$(cargo run --quiet --locked -p runseal -- :guard version-hash)
echo "value=$hash" >> "$GITHUB_OUTPUT"

- name: Create checksums
run: sh .github/scripts/release/assets/checksums.sh "${RELEASE_VERSION}" "${RELEASE_ROOT}"

Expand All @@ -168,6 +184,8 @@ jobs:

- name: Publish to R2
id: r2
env:
GUARD_VERSION_HASH: ${{ steps.guard_hash.outputs.value }}
run: bash .github/scripts/release/r2/publish.sh

- name: Verify R2 publish
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/release-stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ jobs:
id: stable
run: python3 .github/scripts/release/metadata/stable.py

- name: Guard version policy
shell: bash
run: |
set -euo pipefail
PATH="$PWD/target/debug:$PATH" cargo run --quiet --locked -p runseal -- :guard version-check

verify:
needs: metadata
runs-on: ubuntu-latest
Expand All @@ -72,6 +78,7 @@ jobs:
run: cargo clippy --locked --workspace --all-targets -- -D warnings

- name: Install Flavor
shell: bash
run: |
set -euo pipefail
curl -fsSL https://flavor.perish.uk/manage.sh -o "$RUNNER_TEMP/manage-flavor.sh"
Expand Down Expand Up @@ -155,6 +162,15 @@ jobs:
path: dist/${{ needs.metadata.outputs.release_version }}
merge-multiple: true

- name: Resolve guard version hash
id: guard_hash
shell: bash
run: |
set -euo pipefail
PATH="$PWD/target/debug:$PATH"
hash=$(cargo run --quiet --locked -p runseal -- :guard version-hash)
echo "value=$hash" >> "$GITHUB_OUTPUT"

- name: Create checksums
run: sh .github/scripts/release/assets/checksums.sh "${RELEASE_VERSION}" "${RELEASE_ROOT}"

Expand All @@ -166,6 +182,8 @@ jobs:

- name: Publish to R2
id: r2
env:
GUARD_VERSION_HASH: ${{ steps.guard_hash.outputs.value }}
run: bash .github/scripts/release/r2/publish.sh

- name: Verify R2 publish
Expand All @@ -174,6 +192,7 @@ jobs:
run: bash .github/scripts/release/r2/verify.sh

- name: Create and push git tag
shell: bash
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
Expand Down
39 changes: 39 additions & 0 deletions .runseal/hooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env sh
# runseal init hook: generated by runseal :init
set -eu

if [ "$#" -ne 1 ] || [ ! -f "$1" ]; then
echo "commit message file not found" >&2
exit 1
fi

subject=$(sed -n '
/^[[:space:]]*#/d
/[^[:space:]]/ {
s/^[[:space:]]*//
s/[[:space:]]*$//
p
q
}
' "$1")

if [ -z "$subject" ]; then
echo "commit subject is empty" >&2
exit 1
fi

case "$subject" in
"Merge "*|"Revert "*|"fixup!"*|"squash!"*)
exit 0
;;
esac

if ! printf '%s\n' "$subject" | grep -Eq '^[a-z][a-z0-9-]*(/[a-z0-9-]+)*: [^[:space:]].*'; then
echo "commit subject must look like '<area>: <imperative summary>'" >&2
echo "actual: $subject" >&2
exit 1
fi

if [ "${#subject}" -gt 72 ]; then
echo "warning: commit subject is ${#subject} chars; prefer <= 72" >&2
fi
7 changes: 7 additions & 0 deletions .runseal/hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env sh
# runseal init hook: generated by runseal :init
set -eu
root=$(git rev-parse --show-toplevel)
cd "$root"

runseal :guard
195 changes: 195 additions & 0 deletions .runseal/wrappers/guard.seal
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
print() {
printf '%s\n' "$1"
}

error() {
printf '%s\n' "$1" >&2
}

fail() {
error "$1"
exit 1
}

usage() {
print "Usage: runseal :guard [version-check|version-hash]"
print ""
print "Run repository guard checks or one explicit version-policy helper."
print ""
print "Commands:"
print " version-check validate version policy against stable metadata"
print " version-hash print the current guard.version.hash value"
}

mode=full
if [ "$#" -gt 0 ]; then
case "$1" in
version-check)
mode=version-check
shift
;;
version-hash)
mode=version-hash
shift
;;
-h|--help|help)
usage
exit 0
;;
*)
fail "guard: unknown command: $1"
;;
esac
fi

if [ "$#" -gt 0 ]; then
fail "guard: unexpected arguments"
fi

if [ "$mode" = version-hash ]; then
runseal @tool hash tree app/tests
exit 0
fi

public_url="${RUNSEAL_RELEASES_PUBLIC_URL:-}"
if [ -z "$public_url" ]; then
public_url="https://releases.runseal.perish.uk"
fi

metadata_url="${RUNSEAL_STABLE_METADATA_URL:-}"
if [ -z "$metadata_url" ]; then
metadata_url="$public_url/stable/latest/metadata.json"
fi

tmp_dir="${RUNSEAL_REPO_TMP_DIR:-.local/tmp}"
if [ -n "${RUNNER_TEMP:-}" ]; then
tmp_dir="${RUNNER_TEMP}/runseal-guard"
fi
runseal @tool fs mkdir "$tmp_dir" 700
metadata_file="$tmp_dir/runseal-guard-stable-metadata.json"
cargo_metadata=$(cargo metadata --no-deps --format-version 1)
current_version=$(runseal @tool json get "$cargo_metadata" '.packages[0].version')
current_hash=$(runseal @tool hash tree app/tests)
status=$(curl -sS -o "$metadata_file" -w "%{http_code}" "$metadata_url?version=$current_version")
if [ "$status" = 404 ]; then
print "guard version policy: no stable metadata; skipping"
if [ "$mode" = version-check ]; then
exit 0
fi
else
if [ "$status" = 200 ]; then
else
fail "guard version policy: failed to fetch stable metadata: HTTP $status"
fi

metadata=$(cat "$metadata_file")
has_prior_hash=$(runseal @tool json has "$metadata" .guard.version.hash)
if [ "$has_prior_hash" = true ]; then
prior_hash=$(runseal @tool json get "$metadata" .guard.version.hash)
else
prior_hash=
fi
if [ -z "$prior_hash" ]; then
print "guard version policy: stable metadata has no guard.version.hash; skipping"
if [ "$mode" = version-check ]; then
exit 0
fi
else
has_stable_version=$(runseal @tool json has "$metadata" .stableVersion)
if [ "$has_stable_version" = true ]; then
prior_version=$(runseal @tool json get "$metadata" .stableVersion)
else
prior_version=
fi
if [ -z "$prior_version" ]; then
has_release_version=$(runseal @tool json has "$metadata" .releaseVersion)
if [ "$has_release_version" = true ]; then
prior_version=$(runseal @tool json get "$metadata" .releaseVersion)
fi
fi
if [ -z "$prior_version" ]; then
fail "guard version policy: stable metadata is missing stableVersion/releaseVersion"
fi

current_order=$(runseal @tool version compare "$current_version" "$prior_version")
prior_major=$(runseal @tool version part "$prior_version" major)
prior_minor=$(runseal @tool version part "$prior_version" minor)
current_major=$(runseal @tool version part "$current_version" major)
current_minor=$(runseal @tool version part "$current_version" minor)
same_minor_lineage=false

if [ "$current_order" = lt ]; then
fail "guard version policy: version regressed below prior stable $prior_version"
fi
if [ "$current_order" = eq ]; then
fail "guard version policy: version matches prior stable $prior_version"
fi
if [ "$current_major" = "$prior_major" ]; then
if [ "$current_minor" = "$prior_minor" ]; then
same_minor_lineage=true
fi
fi

if [ "$current_hash" = "$prior_hash" ]; then
if [ "$same_minor_lineage" = false ]; then
fail "guard version policy: unchanged guard.version.hash requires a patch-only bump above $prior_version"
fi
print "guard version policy: hash unchanged -> patch bump ok ($prior_version -> $current_version)"
else
if [ "$same_minor_lineage" = true ]; then
fail "guard version policy: changed guard.version.hash requires a minor-or-higher bump above $prior_version"
fi
print "guard version policy: hash changed -> minor-or-higher bump ok ($prior_version -> $current_version)"
fi

if [ "$mode" = version-check ]; then
exit 0
fi
fi
fi

print "==> cargo fmt"
cargo fmt --all --check

print "==> cargo clippy"
cargo clippy --locked --workspace --all-targets -- -D warnings

print "==> cargo test"
cargo test --locked --workspace

print "==> seal wrappers"
cargo run --quiet --locked -p runseal -- @transpile --input-lang=seal --output-lang=sealir .runseal/wrappers/cloudflare.seal
cargo run --quiet --locked -p runseal -- @transpile --input-lang=seal --output-lang=sealir .runseal/wrappers/guard.seal
cargo run --quiet --locked -p runseal -- @transpile --input-lang=seal --output-lang=sealir .runseal/wrappers/init.seal
cargo run --quiet --locked -p runseal -- @transpile --input-lang=seal --output-lang=sealir .runseal/wrappers/pr.seal
cargo run --quiet --locked -p runseal -- @transpile --input-lang=seal --output-lang=sealir .runseal/wrappers/release.seal

print "==> flavor self-check"
flavor check --root . --config flavor.toml

print "==> shell syntax"
sh -n manage.sh
sh -n .github/scripts/release/assets/checksums.sh
sh -n .github/scripts/release/assets/package.sh
sh -n .github/scripts/release/assets/verify.sh
sh -n .github/scripts/release/github/cleanup-artifacts.sh
bash -n .github/scripts/release/r2/check.sh
bash -n .github/scripts/release/r2/publish.sh
bash -n .github/scripts/release/r2/summary.sh
bash -n .github/scripts/release/r2/verify.sh
sh -n .github/scripts/release/smoke/smoke.sh

print "==> python syntax"
python3 -m py_compile .github/scripts/release/metadata/beta.py
python3 -m py_compile .github/scripts/release/metadata/stable.py

has_pwsh=$(runseal @tool process exists pwsh)
if [ "$has_pwsh" = true ]; then
print "==> PowerShell syntax"
pwsh -NoProfile -NonInteractive -Command "[scriptblock]::Create((Get-Content -Raw 'manage.ps1')) | Out-Null"
pwsh -NoProfile -NonInteractive -Command "[scriptblock]::Create((Get-Content -Raw '.github/scripts/release/assets/package.ps1')) | Out-Null"
pwsh -NoProfile -NonInteractive -Command "[scriptblock]::Create((Get-Content -Raw '.github/scripts/release/smoke/smoke.ps1')) | Out-Null"
else
print "==> PowerShell syntax"
print "skip: pwsh not found"
fi
Loading
Loading