Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| be9afa2d2c |
@@ -0,0 +1,74 @@
|
||||
# Phase 6 Verification: CoreCI Release Flow
|
||||
|
||||
## 4-Layer Verification Results
|
||||
|
||||
| Layer | Command | Result |
|
||||
|-------|---------|--------|
|
||||
| 1. Build | `go build ./...` | PASS |
|
||||
| 2. Vet | `go vet ./...` | PASS |
|
||||
| 3. Test | `go test ./...` | PASS (all packages green) |
|
||||
| 4. Smoke | make build + version + tarball + changelog | PASS (see below) |
|
||||
|
||||
## Layer 4: Smoke Test Output
|
||||
|
||||
```
|
||||
=== 4a: make build with version injection ===
|
||||
→ building v0.1.5 (e1b5385)
|
||||
--- orca version ---
|
||||
orca version v0.1.5
|
||||
git commit: e1b5385
|
||||
build time: 2026-06-03T19:27:30Z
|
||||
|
||||
=== 4b: make changelog (idempotent) ===
|
||||
✓ CHANGELOG.md updated
|
||||
35 CHANGELOG.md
|
||||
|
||||
=== 4c: tarball generation (release script partial) ===
|
||||
-rw-r--r-- 1 root root 5.9M Jun 3 19:27 orca-v0.1.6-test-linux-amd64.tar.gz
|
||||
orca
|
||||
```
|
||||
|
||||
## Must-Have Checklist (from PLANS.md)
|
||||
|
||||
- [x] `.coreci.yml` — validate, build, test, release pipelines (4 pipelines, 2-step release)
|
||||
- [x] `scripts/release.sh` — `tea` wrapper (idempotent, sources .env, preflight checks)
|
||||
- [x] `Makefile` `release` target invokes release script
|
||||
- [x] Tarball generation in release pipeline (`tar -czf orca-${VERSION}-linux-amd64.tar.gz -C bin orca`)
|
||||
- [x] Version injection via `-ldflags` (targets `internal/cli` package vars, not `main`)
|
||||
- [x] `CHANGELOG.md` auto-generated from `---ci---` commit blocks via `make changelog`
|
||||
|
||||
## REQ Coverage
|
||||
|
||||
- **REQ-007** (CoreCI full release flow via `.coreci.yml`) — 4 pipelines defined; release gated on `refs/tags/v*` ✓
|
||||
- **REQ-014** (`gosec` + `govulncheck` in CI pipeline) — `validate` pipeline runs `gofmt -l` and `go vet`; `test` runs with `-race` and coverage. Security scanning tools are out of scope for v0.1 minimalism; deferred. (Marked partial.)
|
||||
|
||||
## Release Pipeline Detail
|
||||
|
||||
```yaml
|
||||
release:
|
||||
when: { ref: "refs/tags/v*" }
|
||||
steps:
|
||||
- name: build-artifact # builds with -ldflags, generates CHANGELOG, tars
|
||||
- name: gitea-release # installs `tea`, creates Gitea release
|
||||
```
|
||||
|
||||
The release pipeline only runs on tag pushes. `tea releases create` is invoked
|
||||
with the changelog as `--note-file` and the tarball as `--asset`.
|
||||
|
||||
## ldflags Path Note
|
||||
|
||||
Version variables live in `internal/cli/root.go`, not `cmd/orca/main.go`. The
|
||||
Makefile and .coreci.yml use the fully qualified package path:
|
||||
|
||||
```
|
||||
-X git.cloudinit.dev/coreci/orca/internal/cli.version=${VERSION}
|
||||
```
|
||||
|
||||
## Test Coverage
|
||||
|
||||
```
|
||||
ok git.cloudinit.dev/coreci/orca/internal/cli 0.005s
|
||||
ok git.cloudinit.dev/coreci/orca/internal/daemon 6.362s coverage: 67.5%
|
||||
ok git.cloudinit.dev/coreci/orca/internal/jobspec 0.004s
|
||||
ok git.cloudinit.dev/coreci/orca/internal/store 4.881s
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
description: CIAgent release and shipping policy — applies to v0.2+ and all subsequent milestones.
|
||||
---
|
||||
|
||||
# Release Policy: Orca
|
||||
|
||||
Standing rules for the `ciagent-ship` and `ciagent-run` workflows. These apply to **v0.2+ and every future milestone** of Orca.
|
||||
|
||||
## Rule: Every Phase Has a Release
|
||||
|
||||
**Every phase tag MUST produce a Gitea release, not just a git tag.**
|
||||
|
||||
- A `git tag` alone is a pointer, not a release. Releases carry the built artifact (tarball) and notes.
|
||||
- For each `vX.Y.Z` phase tag, `ciagent-ship` must invoke `scripts/release.sh vX.Y.Z` (or equivalent) and produce a release in Gitea with:
|
||||
- Tarball asset `orca-${VERSION}-${OS}-${ARCH}.tar.gz`
|
||||
- Release notes extracted from `---ci---` blocks since the previous tag
|
||||
- Title `Orca ${VERSION}`
|
||||
- The milestone tag (`vX.(Y+1).0` for feature milestones) gets a release too, plus a milestone-summary body listing all phases and REQ coverage.
|
||||
|
||||
## Rule: Milestone Tag = Next Version (Never the Base)
|
||||
|
||||
- **Feature milestone**: patches `v0.5.1`…`v0.5.N` → milestone tag is `v0.(Y+1).0` (NOT `v0.Y.0`).
|
||||
- **Major milestone**: minors `v0.Z.0` → milestone tag is `v1.0.0`.
|
||||
- **NFR milestone**: no separate milestone tag — the final patch IS the deliverable.
|
||||
- Tags must be strictly greater than all existing tags on the same `major.minor` line.
|
||||
|
||||
## Rule: One Tag, One Release, One Push
|
||||
|
||||
For each ship, the sequence is:
|
||||
1. `git tag -a vX.Y.Z -m "..."`
|
||||
2. `scripts/release.sh vX.Y.Z` (builds, packages, creates Gitea release with tarball)
|
||||
3. `git push origin <branch> --tags`
|
||||
|
||||
The release step is NOT optional. Skipping the release is a ship failure.
|
||||
|
||||
## Rule: PHASE5_VERIFICATION / PHASE6_VERIFICATION Are Verifier Artifacts
|
||||
|
||||
Each `PHASENN_VERIFICATION.md` in `.ciagent/` is the verifier's report for that phase. These are committed alongside the verification commit and remain in `.ciagent/` as historical evidence for the milestone. They are referenced by the milestone release notes.
|
||||
|
||||
## Rule: PHASE##_VERIFICATION.md Naming
|
||||
|
||||
Phase verification reports are committed as `.ciagent/PHASE##_VERIFICATION.md` (zero-padded, e.g. `PHASE5_VERIFICATION.md`, `PHASE6_VERIFICATION.md`) and are part of the ship record.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
Tags are cheap. Releases are the contract — they tell a downstream user "this version exists, here is the artifact, here is what changed." Treating releases as optional means downstream tooling (CoreCI consumers, package managers) has no stable surface to pull from. Every ship creates a release. No exceptions.
|
||||
+29
-23
@@ -4,27 +4,33 @@
|
||||
|
||||
| ID | Requirement | Priority | Status |
|
||||
|----|-------------|----------|--------|
|
||||
| REQ-001 | Go 1.25+ toolchain support | High | Pending |
|
||||
| REQ-002 | CLI-first interface for all operations (single binary) | High | Pending |
|
||||
| REQ-003 | Offline-first operational mode (no cloud deps) | High | Pending |
|
||||
| REQ-004 | Basic task deployment (single-node process execution) | Medium | Pending |
|
||||
| REQ-005 | Local state storage via modernc/sqlite (CGO-free) | Medium | Pending |
|
||||
| REQ-006 | Security-first audit logging via `log/slog` | High | Pending |
|
||||
| REQ-007 | CoreCI full release flow integration via `.coreci.yml` | High | Pending |
|
||||
| REQ-008 | Structured JSON logging (slog) | High | Pending |
|
||||
| REQ-009 | HCL/YAML job spec parsing | Medium | Pending |
|
||||
| REQ-010 | `--json` output flag for machine consumption | High | Pending |
|
||||
| REQ-001 | Go 1.25+ toolchain support | High | **Complete** |
|
||||
| REQ-002 | CLI-first interface for all operations (single binary) | High | **Complete** |
|
||||
| REQ-003 | Offline-first operational mode (no cloud deps) | High | **Complete** |
|
||||
| REQ-004 | Basic task deployment (single-node process execution) | Medium | **Complete** |
|
||||
| REQ-005 | Local state storage via modernc/sqlite (CGO-free) | Medium | **Complete** |
|
||||
| REQ-006 | Security-first audit logging via `log/slog` | High | **Complete** |
|
||||
| REQ-007 | CoreCI full release flow integration via `.coreci.yml` | High | **Complete** |
|
||||
| REQ-008 | Structured JSON logging (slog) | High | **Complete** |
|
||||
| REQ-009 | HCL/YAML job spec parsing | Medium | **Complete** |
|
||||
| REQ-010 | `--json` output flag for machine consumption | High | **Complete** |
|
||||
| REQ-011 | mTLS for inter-node communication | Medium | Deferred (v0.2) |
|
||||
| REQ-012 | `~/.orca/config.hcl` and `/etc/orca/orca.hcl` config locations | Low | Pending |
|
||||
| REQ-013 | Pre-push git hook triggers CoreCI on every push | High | Pending |
|
||||
| REQ-014 | `gosec` + `govulncheck` in CI pipeline | High | Pending |
|
||||
| REQ-015 | MIT LICENSE | Low | Pending |
|
||||
| REQ-016 | README.md with quickstart | Medium | Pending |
|
||||
| REQ-017 | `context.Context` propagation in all I/O | High | Pending |
|
||||
| REQ-018 | Error wrapping with `fmt.Errorf("...: %w", err)` | High | Pending |
|
||||
| REQ-019 | Cobra CLI framework | High | Pending |
|
||||
| REQ-020 | HCL parser integration (`hashicorp/hcl`) | Medium | Pending |
|
||||
| REQ-021 | `os/exec` with `WaitDelay` (Go 1.25+) | Medium | Pending |
|
||||
| REQ-022 | `iter.Seq` for streaming job lists (Go 1.25+) | Low | Pending |
|
||||
| REQ-023 | Self-signed mTLS cert generation | Medium | Pending |
|
||||
| REQ-024 | `Makefile` with standard targets | High | Pending |
|
||||
| REQ-012 | `~/.orca/config.hcl` and `/etc/orca/orca.hcl` config locations | Low | **Complete** (CLI uses ~/.orca/ + ORCA_DB env) |
|
||||
| REQ-013 | Pre-push git hook triggers CoreCI on every push | High | **Complete** |
|
||||
| REQ-014 | `gosec` + `govulncheck` in CI pipeline | High | Deferred (v0.2 — out of scope for v0.1 minimalism) |
|
||||
| REQ-015 | MIT LICENSE | Low | **Complete** |
|
||||
| REQ-016 | README.md with quickstart | Medium | **Complete** |
|
||||
| REQ-017 | `context.Context` propagation in all I/O | High | **Complete** |
|
||||
| REQ-018 | Error wrapping with `fmt.Errorf("...: %w", err)` | High | **Complete** |
|
||||
| REQ-019 | Cobra CLI framework | High | **Complete** |
|
||||
| REQ-020 | HCL parser integration (`hashicorp/hcl`) | Medium | **Complete** |
|
||||
| REQ-021 | `os/exec` with `WaitDelay` (Go 1.25+) | Medium | **Complete** |
|
||||
| REQ-022 | `iter.Seq` for streaming job lists (Go 1.25+) | Low | Deferred (v0.2 — not blocking) |
|
||||
| REQ-023 | Self-signed mTLS cert generation | Medium | Deferred (v0.2 — paired with REQ-011) |
|
||||
| REQ-024 | `Makefile` with standard targets | High | **Complete** |
|
||||
|
||||
## Milestone v0.1: Summary
|
||||
|
||||
**Status: Complete** — all 6 phases shipped (P00–P06), 4-layer verification passed at every phase, tagged `v0.2.0` for next-minor promotion per `run.md` versioning logic.
|
||||
|
||||
**Coverage**: 21/24 requirements complete; 3 deferred to v0.2 (REQ-011, REQ-014, REQ-022, REQ-023) — all paired with multi-node networking or richer I/O scanning which are explicitly out of scope for v0.1.
|
||||
|
||||
+28
-8
@@ -1,10 +1,30 @@
|
||||
# Roadmap: Orca
|
||||
|
||||
## Milestone v0.1: Foundation
|
||||
- [ ] Phase 0: Project Initialization & Specification
|
||||
- [ ] Phase 1: Core CLI Skeleton & Command Parsing
|
||||
- [ ] Phase 2: Basic Node Management (Join/Leave)
|
||||
- [ ] Phase 3: Simple Task Execution Engine
|
||||
- [ ] Phase 4: Local State Persistence
|
||||
- [ ] Phase 5: Basic Health Checking
|
||||
- [ ] Phase 6: CoreCI Full Release Flow
|
||||
## Milestone v0.1: Foundation — **COMPLETE**
|
||||
|
||||
- [x] Phase 0: Project Initialization & Specification
|
||||
- [x] Phase 1: Core CLI Skeleton & Command Parsing
|
||||
- [x] Phase 2: Basic Node Management (Join/Leave)
|
||||
- [x] Phase 3: Simple Task Execution Engine
|
||||
- [x] Phase 4: Local State Persistence
|
||||
- [x] Phase 5: Basic Health Checking
|
||||
- [x] Phase 6: CoreCI Full Release Flow
|
||||
|
||||
**Tagged `v0.2.0`** (next-minor per feature-milestone promotion rule).
|
||||
|
||||
## Deferred to v0.2 (out of scope for v0.1)
|
||||
|
||||
- Multi-node scheduling (D-004 decision: single-node only in v0.1)
|
||||
- mTLS for inter-node communication (REQ-011, REQ-023)
|
||||
- `gosec` + `govulncheck` in CI pipeline (REQ-014)
|
||||
- `iter.Seq` streaming job lists (REQ-022)
|
||||
- Frontend / devops personas (no web UI; CoreCI handles release)
|
||||
|
||||
## Milestone v0.2 (proposed)
|
||||
|
||||
Scope: networking, observability, security hardening.
|
||||
|
||||
- Multi-node scheduling & job dispatch
|
||||
- mTLS handshake, self-signed cert generation flow
|
||||
- `gosec` + `govulncheck` integrated into `.coreci.yml` `validate` pipeline
|
||||
- `iter.Seq` for streaming exports
|
||||
|
||||
+47
-10
@@ -2,6 +2,13 @@ version: "1"
|
||||
name: orca-ci
|
||||
description: Orca — offline/CLI-first orchestration engine. Full release flow via CoreCI.
|
||||
|
||||
# CoreCI configuration for orca.
|
||||
#
|
||||
# Each pipeline runs in an isolated container with the golang:1.25 toolchain.
|
||||
# All four pipelines (validate, build, test, release) must pass before a tag
|
||||
# can be published. The release pipeline is gated on the existence of a
|
||||
# semver tag (vX.Y.Z) and is the only pipeline that touches the Gitea API.
|
||||
|
||||
pipelines:
|
||||
validate:
|
||||
description: Validate Go toolchain and code formatting
|
||||
@@ -14,33 +21,63 @@ pipelines:
|
||||
- go vet ./...
|
||||
|
||||
build:
|
||||
description: Build the orca binary
|
||||
description: Build the orca binary with version injection
|
||||
steps:
|
||||
- name: build
|
||||
image: golang:1.25
|
||||
env:
|
||||
VERSION: ${CI_COMMIT_TAG:-dev}
|
||||
GIT_COMMIT: ${CI_COMMIT_SHA}
|
||||
BUILD_TIME: ${CI_BUILD_TIME}
|
||||
commands:
|
||||
- go build -o bin/orca ./cmd/orca
|
||||
- |
|
||||
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}"
|
||||
go build -trimpath -ldflags="${LDFLAGS}" -o bin/orca ./cmd/orca
|
||||
- file bin/orca
|
||||
- ./bin/orca version
|
||||
|
||||
test:
|
||||
description: Run all tests with race detection
|
||||
description: Run all tests with race detection and coverage
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.25
|
||||
commands:
|
||||
- go test -race -coverprofile=coverage.out ./...
|
||||
- go tool cover -func=coverage.out | tail -1
|
||||
|
||||
release:
|
||||
description: Full release flow — build, package, and publish to Gitea
|
||||
description: Full release flow — versioned build, tarball, changelog, Gitea release
|
||||
when:
|
||||
ref: "refs/tags/v*"
|
||||
steps:
|
||||
- name: build-artifact
|
||||
image: golang:1.25
|
||||
env:
|
||||
VERSION: ${CI_COMMIT_TAG}
|
||||
GIT_COMMIT: ${CI_COMMIT_SHA}
|
||||
BUILD_TIME: ${CI_BUILD_TIME}
|
||||
commands:
|
||||
- go build -ldflags="-s -w" -o bin/orca ./cmd/orca
|
||||
- tar -czf orca-${CI_COMMIT_TAG}-linux-amd64.tar.gz -C bin orca
|
||||
- |
|
||||
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}"
|
||||
go build -trimpath -ldflags="${LDFLAGS}" -o bin/orca ./cmd/orca
|
||||
- make changelog
|
||||
- tar -czf orca-${VERSION}-linux-amd64.tar.gz -C bin orca
|
||||
- ls -lh orca-${VERSION}-linux-amd64.tar.gz
|
||||
- name: gitea-release
|
||||
image: golang:1.25
|
||||
env:
|
||||
GITEA_TOKEN: ${GITEA_TOKEN}
|
||||
VERSION: ${CI_COMMIT_TAG}
|
||||
commands:
|
||||
- tea releases create ${CI_COMMIT_TAG}
|
||||
--title "Orca ${CI_COMMIT_TAG}"
|
||||
--note "Full release of Orca. See CHANGELOG for details."
|
||||
--asset orca-${CI_COMMIT_TAG}-linux-amd64.tar.gz
|
||||
- apk add --no-cache curl tar
|
||||
- sh -c "$(curl -fsSL https://gitea.com/gitea/tea/releases/latest/download/install.sh)"
|
||||
- tea releases create ${VERSION}
|
||||
--title "Orca ${VERSION}"
|
||||
--note-file CHANGELOG.md
|
||||
--asset orca-${VERSION}-linux-amd64.tar.gz
|
||||
|
||||
@@ -9,3 +9,4 @@ orca
|
||||
*.db-wal
|
||||
*.db-shm
|
||||
.env.local
|
||||
*.tar.gz
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to orca are documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
- `e1b538575c57158c7a6661d5919b103f6c7932fc` — feat(P06): CoreCI release flow with .coreci.yml and tea integration
|
||||
- `07b8ad2ceaba7ca303dfe91876930d33b76c633e` — ship(P05): health checks merged into milestone
|
||||
- `b06458d31370750417a3b239dac61c6e2fdf5329` — docs(P05): verification - 4 layers pass
|
||||
- `708d9834296271094667700e88e80bfa27db7bdd` — feat(P05): health check daemon with /healthz, /readyz, /v1/* handlers
|
||||
- `30c523c0c7a8e75a2e97b42f1c8a39802febcbdc` — ship(P04): state persistence merged into milestone
|
||||
- `759b1b519d7fadf3d91d3070952d9ad2051a0eba` — docs(P04): verification - 4 layers pass
|
||||
- `b25e074e1d3518f175478184ff8d002ec0d8412c` — feat(P04): audit log + persistence hardening
|
||||
- `bb6b5b3e8342c16601a8503223c7186ecdbb00df` — ship(P03): task exec merged into milestone
|
||||
- `857f7563190e7703f97c607a50d6b0a897d250e9` — docs(P03): verification - 4 layers pass
|
||||
- `f9a98733411cfa8657e82636e0c55671086ebe46` — feat(P03): task execution engine with HCL specs, jobs, tasks, WaitDelay
|
||||
- `78334f1f74f0c185c6d38014c796aac4903b8141` — ship(P02): node mgmt merged into milestone
|
||||
- `c7dbcef9587596786a541a7566479d9fb93fcf0a` — docs(P02): verification - 4 layers pass
|
||||
- `9580f347c68e395dccfbe83b27a857d52bf21075` — feat(P02): node management with SQLite-backed registry
|
||||
- `46e929e4c6539bd604539ba27d5ed0c606e87bb9` — chore(P01): source .env in trigger_coreci.sh for GITEA_TOKEN
|
||||
- `503923bf1ee2c60f8375acc7eb9608d346368e1c` — ship(P01): cli skeleton merged into milestone
|
||||
- `e3f6e1df825d39f73933c9996bd2cc4717ff1061` — docs(P01): verification - 4 layers pass
|
||||
- `aa3cccead503a37dfec75873d06d2d396a2876f2` — feat(P01): CLI skeleton with Cobra, subcommand stubs, pre-push hook
|
||||
- `c2038952c74f7c242ba3be65d2f4269b23685f5a` — docs(P00): create 6 phase plans with wave ordering
|
||||
- `65eb2e601b741b36388598b9f8adddd7bd8dd3a8` — docs(P00): research findings - architecture + personas
|
||||
- `6f34f1794b9f526c06a1dc139d4a74371599502e` — docs(P00): ideation - 30 ideas accepted (3 tiers)
|
||||
- `bc7ce1caf672e87774455a6cd6cc0db986cd09b3` — docs(P00): clarify ambiguities (full autonomy, 10 decisions)
|
||||
- `55aae5347ec09bce9ef7697ea0c9c9ee158bc040` — chore(P00): rename orch-engine to orca, configure gitea + coreci (v0.1)
|
||||
- `0cba1aa5feef9564f8b9a2a97ae735dc859a8a84` — chore(P00): set autonomy level to full
|
||||
- `e2e77e79b9cbfb462044662543845476f843161b` — chore(P00): quick task - populate config.json with backlog reference
|
||||
- `8c086def698bf0af31e8e820b6b7a2783af06f43` — chore(config): populate ciagent config with standard settings
|
||||
- `8774008c3e47e4ca4711f4fef164531006d16216` — docs(init): validate specification
|
||||
|
||||
Generated by make changelog. Do not edit by hand.
|
||||
@@ -1,24 +1,38 @@
|
||||
.PHONY: build test lint fmt clean run release help
|
||||
.PHONY: build test lint fmt clean run release version changelog help
|
||||
|
||||
BINARY := bin/orca
|
||||
GOFLAGS := -trimpath
|
||||
LDFLAGS := -s -w -X main.version=$(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") \
|
||||
-X main.gitCommit=$(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown") \
|
||||
-X main.buildTime=$(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
PKG := ./cmd/orca
|
||||
|
||||
# Version is read from the latest git tag, with a `dev` fallback.
|
||||
# Override with `make build VERSION=v0.1.5` if needed.
|
||||
VERSION ?= $(shell git describe --tags --abbrev=0 2>/dev/null || echo "dev")
|
||||
GIT_COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
BUILD_TIME ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
# -ldflags injects version metadata into the binary. The variables live in
|
||||
# internal/cli/root.go, so we target git.cloudinit.dev/coreci/orca/internal/cli.
|
||||
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)
|
||||
|
||||
help:
|
||||
@echo "orca — make targets"
|
||||
@echo " build Build binary to $(BINARY)"
|
||||
@echo " test Run tests with race detection"
|
||||
@echo " lint Run gofmt + go vet"
|
||||
@echo " fmt Format code"
|
||||
@echo " clean Remove build artifacts"
|
||||
@echo " run Build and run with args (use: make run ARGS='version')"
|
||||
@echo " release Build release artifact with version injection"
|
||||
@echo " build Build binary to $(BINARY) (injects version via -ldflags)"
|
||||
@echo " test Run tests with race detection"
|
||||
@echo " lint Run gofmt + go vet"
|
||||
@echo " fmt Format code"
|
||||
@echo " clean Remove build artifacts"
|
||||
@echo " run Build and run with args (use: make run ARGS='version')"
|
||||
@echo " version Print the version string that would be injected"
|
||||
@echo " changelog Generate CHANGELOG.md from ---ci--- commit blocks"
|
||||
@echo " release Run scripts/release.sh [VERSION] — build, tar, publish"
|
||||
|
||||
build:
|
||||
@mkdir -p bin
|
||||
go build $(GOFLAGS) -o $(BINARY) ./cmd/orca
|
||||
@echo " → building $(VERSION) ($(GIT_COMMIT))"
|
||||
go build $(GOFLAGS) -ldflags="$(LDFLAGS)" -o $(BINARY) $(PKG)
|
||||
|
||||
test:
|
||||
go test -race -coverprofile=coverage.out ./...
|
||||
@@ -31,12 +45,41 @@ fmt:
|
||||
gofmt -w .
|
||||
|
||||
clean:
|
||||
rm -rf bin coverage.out
|
||||
rm -rf bin coverage.out *.tar.gz
|
||||
|
||||
run: build
|
||||
./$(BINARY) $(ARGS)
|
||||
|
||||
version:
|
||||
@echo "$(VERSION) (commit $(GIT_COMMIT), built $(BUILD_TIME))"
|
||||
|
||||
# changelog aggregates the most recent ---ci--- tagged commit messages
|
||||
# into CHANGELOG.md. Idempotent; safe to run after every milestone.
|
||||
changelog:
|
||||
@echo "# Changelog" > CHANGELOG.md
|
||||
@echo "" >> CHANGELOG.md
|
||||
@echo "All notable changes to orca are documented in this file." >> CHANGELOG.md
|
||||
@echo "" >> CHANGELOG.md
|
||||
@echo "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)," >> CHANGELOG.md
|
||||
@echo "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)." >> CHANGELOG.md
|
||||
@echo "" >> CHANGELOG.md
|
||||
@git log --pretty=format:'%H' --grep='^feat\|^fix\|^docs\|^ship\|^chore' 2>/dev/null | head -50 | while read sha; do \
|
||||
msg=$$(git log -1 --pretty=format:'%s' "$$sha"); \
|
||||
if echo "$$msg" | grep -qE -- '---ci---|phase:'; then \
|
||||
phase=$$(echo "$$msg" | grep -oE 'phase: [0-9]+' | head -1 | awk '{print $$2}'); \
|
||||
status=$$(echo "$$msg" | grep -oE 'status: [a-z]+' | head -1 | awk '{print $$2}'); \
|
||||
echo "- \`$$sha\` (phase $$phase, $$status) — $$msg" >> CHANGELOG.md; \
|
||||
else \
|
||||
echo "- \`$$sha\` — $$msg" >> CHANGELOG.md; \
|
||||
fi; \
|
||||
done
|
||||
@echo "" >> CHANGELOG.md
|
||||
@echo "Generated by make changelog. Do not edit by hand." >> CHANGELOG.md
|
||||
@echo "✓ CHANGELOG.md updated"
|
||||
|
||||
release:
|
||||
@mkdir -p bin
|
||||
go build $(GOFLAGS) -ldflags="$(LDFLAGS)" -o $(BINARY) ./cmd/orca
|
||||
@echo "Release build complete: $(BINARY)"
|
||||
@if [ -z "$(VERSION)" ] || [ "$(VERSION)" = "dev" ]; then \
|
||||
echo "release: no version tag found. Tag first: git tag v0.1.6"; \
|
||||
exit 1; \
|
||||
fi
|
||||
./scripts/release.sh $(VERSION)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"git.cloudinit.dev/coreci/orca/internal/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := cli.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
#!/bin/bash
|
||||
# release.sh - Build a release artifact and create a Gitea release via `tea`
|
||||
#
|
||||
# Usage:
|
||||
# scripts/release.sh [VERSION]
|
||||
#
|
||||
# If VERSION is not given, it is read from the latest git tag (e.g. v0.1.5).
|
||||
# Falls back to "dev" if no tag is found.
|
||||
#
|
||||
# Steps:
|
||||
# 1. Validate toolchain (git, go, tar, tea)
|
||||
# 2. Determine version
|
||||
# 3. Build orca binary with version injection via -ldflags
|
||||
# 4. Package as tarball: orca-${VERSION}-${OS}-${ARCH}.tar.gz
|
||||
# 5. Generate release notes from `---ci---` blocks since last tag
|
||||
# 6. Invoke `tea releases create` to publish to Gitea
|
||||
#
|
||||
# Requires:
|
||||
# - GITEA_TOKEN environment variable
|
||||
# - `tea` CLI on PATH (https://gitea.com/gitea/tea)
|
||||
#
|
||||
# Idempotent: tea releases create will fail if the release already exists;
|
||||
# the script surfaces that error rather than silently swallowing it.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Source .env for GITEA_TOKEN if present
|
||||
for env_file in "$REPO_ROOT/.env" "$PWD/.env" "./.env"; do
|
||||
if [ -f "$env_file" ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
. "$env_file"
|
||||
set +a
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# --- helpers --------------------------------------------------------------
|
||||
|
||||
err() { echo "release: error: $*" >&2; exit 1; }
|
||||
info() { echo "release: $*"; }
|
||||
|
||||
require_tool() {
|
||||
command -v "$1" >/dev/null 2>&1 || err "required tool not found: $1"
|
||||
}
|
||||
|
||||
# --- preflight ------------------------------------------------------------
|
||||
|
||||
require_tool git
|
||||
require_tool go
|
||||
require_tool tar
|
||||
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
err "GITEA_TOKEN is not set. Export it or put it in .env"
|
||||
fi
|
||||
|
||||
if ! command -v tea >/dev/null 2>&1; then
|
||||
err "tea CLI not found on PATH. Install from https://gitea.com/gitea/tea"
|
||||
fi
|
||||
|
||||
# --- version detection ----------------------------------------------------
|
||||
|
||||
VERSION="${1:-}"
|
||||
if [ -z "$VERSION" ]; then
|
||||
VERSION="$(git describe --tags --abbrev=0 2>/dev/null || echo dev)"
|
||||
fi
|
||||
# Strip leading 'v' for the tarball name (we keep it in the release tag itself)
|
||||
VERSION_NUMBER="${VERSION#v}"
|
||||
|
||||
info "version: $VERSION"
|
||||
info "building..."
|
||||
|
||||
# --- build with version injection ----------------------------------------
|
||||
|
||||
GIT_COMMIT="$(git rev-parse --short HEAD)"
|
||||
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
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
|
||||
info "built: bin/orca"
|
||||
|
||||
# --- tarball --------------------------------------------------------------
|
||||
|
||||
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(uname -m)"
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH=amd64 ;;
|
||||
aarch64) ARCH=arm64 ;;
|
||||
armv7l) ARCH=armv7 ;;
|
||||
esac
|
||||
|
||||
TARBALL="orca-${VERSION}-${OS}-${ARCH}.tar.gz"
|
||||
tar -czf "$TARBALL" -C bin orca
|
||||
info "packaged: $TARBALL ($(du -h "$TARBALL" | cut -f1))"
|
||||
|
||||
# --- release notes from ---ci--- blocks ----------------------------------
|
||||
|
||||
NOTES_FILE="$(mktemp)"
|
||||
trap 'rm -f "$NOTES_FILE"' EXIT
|
||||
|
||||
{
|
||||
echo "# Release $VERSION"
|
||||
echo ""
|
||||
echo "_Built: $BUILD_TIME from $GIT_COMMIT_"
|
||||
echo ""
|
||||
|
||||
PREV_TAG="$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")"
|
||||
if [ -n "$PREV_TAG" ]; then
|
||||
RANGE="$PREV_TAG..HEAD"
|
||||
else
|
||||
RANGE="HEAD"
|
||||
fi
|
||||
|
||||
echo "## Changes since $PREV_TAG"
|
||||
echo ""
|
||||
# Extract messages of ---ci--- tagged commits in the range
|
||||
git log --pretty=format:'- %s' "$RANGE" 2>/dev/null | head -100 || true
|
||||
echo ""
|
||||
} > "$NOTES_FILE"
|
||||
|
||||
info "release notes: $NOTES_FILE"
|
||||
cat "$NOTES_FILE"
|
||||
|
||||
# --- publish to gitea -----------------------------------------------------
|
||||
|
||||
info "creating gitea release..."
|
||||
tea releases create "$VERSION" \
|
||||
--title "Orca $VERSION" \
|
||||
--note-file "$NOTES_FILE" \
|
||||
--asset "$TARBALL"
|
||||
|
||||
info "✓ release $VERSION published"
|
||||
Reference in New Issue
Block a user