b8f766de03
The Gitea Actions runner (ubuntu-latest) uses dash as /bin/sh. The previous script used #!/bin/bash with 'set -uo pipefail' — pipefail is bash-only and causes 'set: illegal option -o pipefail' (exit 2) in dash. This was the root cause of the build job failing in 2 seconds. Fix: #!/bin/sh with 'set -u' only (no pipefail). Removed bash-only features. The script is POSIX-compliant. ---ci--- project: orca phase: 1 milestone: v0.16 status: execute ---/ci---
197 lines
8.6 KiB
Bash
Executable File
197 lines
8.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# ci-run.sh — CoreCI pipeline runner for orca.
|
|
# Called by .coreci.yml jobs via: sh scripts/ci-run.sh <job-name>
|
|
#
|
|
# CoreCI's ValidateShellCommand forbids shell metacharacters (&|;`><$())
|
|
# in the invoke: string. This script wraps the complex logic so the
|
|
# invoke: field is just "sh scripts/ci-run.sh <job-name>".
|
|
#
|
|
# Environment variables (provided by CoreCI's CI context + PassThroughEnv):
|
|
# CI_COMMIT_BRANCH — tag name on tag pushes (from GITHUB_REF_NAME)
|
|
# CI_COMMIT_SHA — commit SHA
|
|
# GITEA_TOKEN — Gitea API token (from Gitea Actions secret PAT_TOKEN)
|
|
#
|
|
# NOTE: uses #!/bin/sh — do NOT use bash-only features (pipefail, [[ ]], etc.)
|
|
# The Gitea Actions runner uses dash as /bin/sh.
|
|
|
|
set -u
|
|
|
|
JOB="${1:-}"
|
|
if [ -z "$JOB" ]; then
|
|
echo "usage: sh scripts/ci-run.sh <job-name>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# CoreCI's shell-isolated executor (buildIsolatedEnv) does NOT forward
|
|
# Go toolchain env vars (GOROOT, GOPATH, GOCACHE, GOMODCACHE are in the
|
|
# systemVars deny-list). Re-derive them from the `go` binary on PATH so
|
|
# Go commands work in the shell-isolated executor.
|
|
echo "ci-run: PATH=$PATH" >&2
|
|
echo "ci-run: which go=$(command -v go 2>/dev/null || echo 'not found')" >&2
|
|
if command -v go >/dev/null 2>&1; then
|
|
export GOROOT="${GOROOT:-$(go env GOROOT 2>/dev/null || echo "")}"
|
|
export GOPATH="${GOPATH:-$(go env GOPATH 2>/dev/null || echo "$HOME/go")}"
|
|
export GOCACHE="${GOCACHE:-$(go env GOCACHE 2>/dev/null || echo "$HOME/.cache/go-build")}"
|
|
export GOMODCACHE="${GOMODCACHE:-$(go env GOMODCACHE 2>/dev/null || echo "$HOME/go/pkg/mod")}"
|
|
echo "ci-run: GOROOT=$GOROOT GOPATH=$GOPATH GOCACHE=$GOCACHE GOMODCACHE=$GOMODCACHE" >&2
|
|
fi
|
|
|
|
info() { echo "ci-run: $*"; }
|
|
err() { echo "ci-run: error: $*" >&2; exit 1; }
|
|
|
|
case "$JOB" in
|
|
# ── validate ──────────────────────────────────────────────────────
|
|
go-vet)
|
|
go version
|
|
gofmt -l .
|
|
go vet ./...
|
|
;;
|
|
|
|
verify-reqs)
|
|
make verify-reqs
|
|
;;
|
|
|
|
gosec)
|
|
go install github.com/securego/gosec/v2/cmd/gosec@v2.18.2
|
|
gosec -fmt text -quiet ./...
|
|
;;
|
|
|
|
govulncheck)
|
|
go install golang.org/x/vuln/cmd/govulncheck@v1.1.3
|
|
govulncheck -mode binary ./...
|
|
;;
|
|
|
|
gitleaks)
|
|
curl -fsSL https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks-linux-amd64.tar.gz -o /tmp/gitleaks.tar.gz
|
|
tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks
|
|
mv /tmp/gitleaks /usr/local/bin/gitleaks 2>/dev/null || cp /tmp/gitleaks ./gitleaks
|
|
chmod +x ./gitleaks 2>/dev/null || true
|
|
if [ -x ./gitleaks ]; then
|
|
./gitleaks detect --source . --config .gitleaks.toml --baseline-path .gitleaks-baseline.json --no-banner
|
|
else
|
|
gitleaks detect --source . --config .gitleaks.toml --baseline-path .gitleaks-baseline.json --no-banner
|
|
fi
|
|
;;
|
|
|
|
# ── build ──────────────────────────────────────────────────────────
|
|
build)
|
|
info "building orca binary..."
|
|
VERSION="${CI_COMMIT_BRANCH:-dev}"
|
|
GIT_COMMIT="${CI_COMMIT_SHA:-unknown}"
|
|
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
info "VERSION=$VERSION GIT_COMMIT=$GIT_COMMIT BUILD_TIME=$BUILD_TIME"
|
|
LDFLAGS="-s -w \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.version=${VERSION} \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.gitCommit=${GIT_COMMIT} \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.buildTime=${BUILD_TIME}"
|
|
mkdir -p bin
|
|
info "running: go build -trimpath -ldflags=... -o bin/orca ./cmd/orca"
|
|
go build -trimpath -ldflags="${LDFLAGS}" -o bin/orca ./cmd/orca 2>&1 || err "go build failed with exit $?"
|
|
file bin/orca 2>/dev/null || echo "file command not available"
|
|
./bin/orca version 2>&1 || echo "orca version failed"
|
|
;;
|
|
|
|
# ── test (REQ-031: -race) ─────────────────────────────────────────
|
|
test)
|
|
go test -race -coverprofile=coverage.out ./...
|
|
go tool cover -func=coverage.out | tail -1
|
|
;;
|
|
|
|
# ── release ────────────────────────────────────────────────────────
|
|
release)
|
|
VERSION="${CI_COMMIT_BRANCH:-dev}"
|
|
GIT_COMMIT="${CI_COMMIT_SHA:-unknown}"
|
|
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
TARBALL="orca-${VERSION}-linux-amd64.tar.gz"
|
|
|
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
|
err "GITEA_TOKEN is not set"
|
|
fi
|
|
|
|
# Build the release binary with version injection.
|
|
LDFLAGS="-s -w \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.version=${VERSION} \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.gitCommit=${GIT_COMMIT} \
|
|
-X git.cloudinit.dev/coreci/orca/internal/cli.buildTime=${BUILD_TIME}"
|
|
mkdir -p bin
|
|
go build -trimpath -ldflags="${LDFLAGS}" -o bin/orca ./cmd/orca
|
|
make changelog
|
|
tar -czf "${TARBALL}" -C bin orca
|
|
sha256sum "${TARBALL}" > SHA256SUMS
|
|
ls -lh "${TARBALL}" SHA256SUMS
|
|
cat SHA256SUMS
|
|
|
|
# Install tea CLI for Gitea release creation.
|
|
sh -c "$(curl -fsSL https://gitea.com/gitea/tea/releases/latest/download/install.sh)" 2>/dev/null || true
|
|
|
|
# Create release with assets. If the release already exists (created
|
|
# by the CIAgent ship workflow with title+body but no binary), fall
|
|
# back to attaching assets via the Gitea API.
|
|
info "creating gitea release ${VERSION}..."
|
|
if tea releases create "${VERSION}" \
|
|
--repo coreci/orca \
|
|
--title "Orca ${VERSION}" \
|
|
--note-file CHANGELOG.md \
|
|
--asset "${TARBALL}" \
|
|
--asset SHA256SUMS 2>/dev/null; then
|
|
info "release created via tea"
|
|
else
|
|
info "release may already exist — attaching assets via Gitea API..."
|
|
RELEASE_ID=$(curl -fsSL \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/tags/${VERSION}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
| python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "")
|
|
if [ -n "${RELEASE_ID}" ]; then
|
|
info "attaching assets to release ID ${RELEASE_ID}..."
|
|
curl -fsSL -X POST \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/${RELEASE_ID}/assets?name=${TARBALL}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-F "attachment=@${TARBALL}"
|
|
curl -fsSL -X POST \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/${RELEASE_ID}/assets?name=SHA256SUMS" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-F "attachment=@SHA256SUMS"
|
|
info "assets attached via API"
|
|
else
|
|
err "could not resolve release ID for ${VERSION}"
|
|
fi
|
|
fi
|
|
|
|
# Verify assets are actually attached (REQ-097, gate C-21).
|
|
ASSET_COUNT=$(curl -fsSL \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/tags/${VERSION}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
| python3 -c "import json,sys; print(len(json.load(sys.stdin).get('attachments',[])))" 2>/dev/null || echo "0")
|
|
info "release ${VERSION} has ${ASSET_COUNT} assets"
|
|
if [ "${ASSET_COUNT}" -lt 2 ]; then
|
|
info "assets missing after tea — attempting manual attachment..."
|
|
RELEASE_ID=$(curl -fsSL \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/tags/${VERSION}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
| python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "")
|
|
if [ -n "${RELEASE_ID}" ]; then
|
|
curl -fsSL -X POST \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/${RELEASE_ID}/assets?name=${TARBALL}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-F "attachment=@${TARBALL}"
|
|
curl -fsSL -X POST \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/${RELEASE_ID}/assets?name=SHA256SUMS" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-F "attachment=@SHA256SUMS"
|
|
ASSET_COUNT=$(curl -fsSL \
|
|
"https://git.cloudinit.dev/api/v1/repos/coreci/orca/releases/tags/${VERSION}" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
| python3 -c "import json,sys; print(len(json.load(sys.stdin).get('attachments',[])))" 2>/dev/null || echo "0")
|
|
info "after retry: ${ASSET_COUNT} assets"
|
|
fi
|
|
if [ "${ASSET_COUNT}" -lt 2 ]; then
|
|
err "assets not attached after retry (REQ-097, C-21)"
|
|
fi
|
|
fi
|
|
info "release ${VERSION} published with ${ASSET_COUNT} binary assets"
|
|
;;
|
|
|
|
*)
|
|
err "unknown job: ${JOB}"
|
|
;;
|
|
esac |