ci: add ECP lint gates and require checks before deploy
This commit is contained in:
parent
fe03ec8f1a
commit
d89d3100f6
4 changed files with 278 additions and 0 deletions
112
.forgejo/workflows/ci-gates.yml
Normal file
112
.forgejo/workflows/ci-gates.yml
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
name: ci-gates
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request: {}
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
checks:
|
||||||
|
runs-on: codeberg-medium-lazy
|
||||||
|
steps:
|
||||||
|
- name: Fetch source (no git required)
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
|
||||||
|
echo "error: missing github.token"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "error: curl is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! command -v tar >/dev/null 2>&1; then
|
||||||
|
echo "error: tar is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ -z "${GITHUB_SHA:-}" ]]; then
|
||||||
|
echo "error: missing GITHUB_SHA"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf .repo
|
||||||
|
mkdir -p .repo
|
||||||
|
curl -fsSL -H "Authorization: token ${GITHUB_TOKEN}" \
|
||||||
|
"https://codeberg.org/api/v1/repos/every-channel/every.channel/archive/${GITHUB_SHA}.tar.gz?rev=${GITHUB_SHA}" \
|
||||||
|
-o .repo/src.tgz
|
||||||
|
tar -xzf .repo/src.tgz -C .repo --strip-components=1
|
||||||
|
rm -f .repo/src.tgz
|
||||||
|
|
||||||
|
- name: Bootstrap Rust + web build tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
install -d -m 755 "$HOME/.local/bin"
|
||||||
|
echo "PATH=$HOME/.local/bin:$PATH" >> "$GITHUB_ENV"
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "error: curl is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v cargo >/dev/null 2>&1; then
|
||||||
|
curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
elif [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
if ! command -v trunk >/dev/null 2>&1; then
|
||||||
|
trunk_version="0.21.14"
|
||||||
|
arch="$(uname -m)"
|
||||||
|
case "${arch}" in
|
||||||
|
x86_64|amd64) trunk_target="x86_64-unknown-linux-gnu" ;;
|
||||||
|
aarch64|arm64) trunk_target="aarch64-unknown-linux-gnu" ;;
|
||||||
|
*)
|
||||||
|
echo "error: unsupported runner arch for trunk prebuilt binary: ${arch}"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
curl -fsSL "https://github.com/trunk-rs/trunk/releases/download/v${trunk_version}/trunk-${trunk_target}.tar.gz" \
|
||||||
|
| tar -xz -C "$HOME/.local/bin" trunk
|
||||||
|
fi
|
||||||
|
|
||||||
|
cargo --version
|
||||||
|
rustc --version
|
||||||
|
trunk --version
|
||||||
|
|
||||||
|
- name: ECP lint
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
bash ./scripts/ecp-lint.sh
|
||||||
|
|
||||||
|
- name: Rust tests (core subset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
if [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
cargo test -p ec-core -p ec-crypto -p ec-moq -p ec-iroh -p ec-linux-iptv
|
||||||
|
|
||||||
|
- name: Build web (apps/web)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
if [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
cd apps/web
|
||||||
|
env -u NO_COLOR trunk build --release --public-url /
|
||||||
|
|
@ -10,7 +10,108 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
checks:
|
||||||
|
runs-on: codeberg-medium-lazy
|
||||||
|
steps:
|
||||||
|
- name: Fetch Source (no git required)
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
|
||||||
|
echo "error: missing github.token"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "error: curl is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if ! command -v tar >/dev/null 2>&1; then
|
||||||
|
echo "error: tar is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
if [[ -z "${GITHUB_SHA:-}" ]]; then
|
||||||
|
echo "error: missing GITHUB_SHA"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf .repo
|
||||||
|
mkdir -p .repo
|
||||||
|
|
||||||
|
curl -fsSL -H "Authorization: token ${GITHUB_TOKEN}" \
|
||||||
|
"https://codeberg.org/api/v1/repos/every-channel/every.channel/archive/${GITHUB_SHA}.tar.gz?rev=${GITHUB_SHA}" \
|
||||||
|
-o .repo/src.tgz
|
||||||
|
tar -xzf .repo/src.tgz -C .repo --strip-components=1
|
||||||
|
rm -f .repo/src.tgz
|
||||||
|
|
||||||
|
- name: Bootstrap Rust + web build tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
install -d -m 755 "$HOME/.local/bin"
|
||||||
|
echo "PATH=$HOME/.local/bin:$PATH" >> "$GITHUB_ENV"
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
echo "error: curl is required"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v cargo >/dev/null 2>&1; then
|
||||||
|
curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
elif [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
|
||||||
|
if ! command -v trunk >/dev/null 2>&1; then
|
||||||
|
trunk_version="0.21.14"
|
||||||
|
arch="$(uname -m)"
|
||||||
|
case "${arch}" in
|
||||||
|
x86_64|amd64) trunk_target="x86_64-unknown-linux-gnu" ;;
|
||||||
|
aarch64|arm64) trunk_target="aarch64-unknown-linux-gnu" ;;
|
||||||
|
*)
|
||||||
|
echo "error: unsupported runner arch for trunk prebuilt binary: ${arch}"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
curl -fsSL "https://github.com/trunk-rs/trunk/releases/download/v${trunk_version}/trunk-${trunk_target}.tar.gz" \
|
||||||
|
| tar -xz -C "$HOME/.local/bin" trunk
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: ECP lint
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
bash ./scripts/ecp-lint.sh
|
||||||
|
|
||||||
|
- name: Rust tests (core subset)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
if [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
cargo test -p ec-core -p ec-crypto -p ec-moq -p ec-iroh -p ec-linux-iptv
|
||||||
|
|
||||||
|
- name: Build site (web)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
cd .repo
|
||||||
|
if [[ -f "$HOME/.cargo/env" ]]; then
|
||||||
|
. "$HOME/.cargo/env"
|
||||||
|
fi
|
||||||
|
cd apps/web
|
||||||
|
env -u NO_COLOR trunk build --release --public-url /
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
|
needs: checks
|
||||||
runs-on: codeberg-medium-lazy
|
runs-on: codeberg-medium-lazy
|
||||||
steps:
|
steps:
|
||||||
- name: Fetch Source (no git required)
|
- name: Fetch Source (no git required)
|
||||||
|
|
|
||||||
3
justfile
3
justfile
|
|
@ -3,6 +3,9 @@ set shell := ["bash", "-eu", "-o", "pipefail", "-c"]
|
||||||
default:
|
default:
|
||||||
@just --list
|
@just --list
|
||||||
|
|
||||||
|
ecp-lint:
|
||||||
|
./scripts/ecp-lint.sh
|
||||||
|
|
||||||
test-core:
|
test-core:
|
||||||
cargo test -p ec-core -p ec-crypto -p ec-moq -p ec-iroh -p ec-linux-iptv
|
cargo test -p ec-core -p ec-crypto -p ec-moq -p ec-iroh -p ec-linux-iptv
|
||||||
|
|
||||||
|
|
|
||||||
62
scripts/ecp-lint.sh
Executable file
62
scripts/ecp-lint.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "${root}"
|
||||||
|
|
||||||
|
min_id="${EVERY_CHANNEL_ECP_LINT_MIN_ID:-63}"
|
||||||
|
|
||||||
|
files=()
|
||||||
|
if [[ "$#" -gt 0 ]]; then
|
||||||
|
for arg in "$@"; do
|
||||||
|
files+=("${arg}")
|
||||||
|
done
|
||||||
|
else
|
||||||
|
while IFS= read -r f; do
|
||||||
|
files+=("${f}")
|
||||||
|
done < <(find evolution/proposals -maxdepth 1 -type f -name 'ECP-*.md' | sort)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${#files[@]}" -eq 0 ]]; then
|
||||||
|
echo "ecp-lint: no ECP files found"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
errors=0
|
||||||
|
|
||||||
|
check_pattern() {
|
||||||
|
local file="$1"
|
||||||
|
local regex="$2"
|
||||||
|
local message="$3"
|
||||||
|
if ! rg -q --pcre2 "${regex}" "${file}"; then
|
||||||
|
echo "ecp-lint: ${file}: ${message}" >&2
|
||||||
|
errors=$((errors + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in "${files[@]}"; do
|
||||||
|
[[ -f "${file}" ]] || continue
|
||||||
|
|
||||||
|
base="$(basename "${file}")"
|
||||||
|
if [[ ! "${base}" =~ ^ECP-([0-9]{4})- ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
id=$((10#${BASH_REMATCH[1]}))
|
||||||
|
if (( id < min_id )); then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_pattern "${file}" '^# ECP-[0-9]{4}:' "missing or invalid title"
|
||||||
|
check_pattern "${file}" '^Status: (Draft|Accepted|Implemented|Superseded|Rejected)$' "missing or invalid Status line"
|
||||||
|
check_pattern "${file}" '^## (Problem|Context|Motivation)\b' "missing Problem/Context/Motivation section"
|
||||||
|
check_pattern "${file}" '^## Decision\b' "missing Decision section"
|
||||||
|
check_pattern "${file}" '^## (Alternatives considered|Alternatives)\b' "missing Alternatives considered section"
|
||||||
|
check_pattern "${file}" '^## (Rollout / teardown|Rollout / teardown plan|Rollout / Reversibility|Rollout|Reversibility)\b' "missing Rollout/teardown (or Reversibility) section"
|
||||||
|
done
|
||||||
|
|
||||||
|
if (( errors > 0 )); then
|
||||||
|
echo "ecp-lint: failed with ${errors} issue(s)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "ecp-lint: ok"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue