diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml new file mode 100644 index 0000000..1a787c6 --- /dev/null +++ b/.forgejo/workflows/deploy.yml @@ -0,0 +1,106 @@ +name: Deploy + +on: + push: + branches: [main] + +concurrency: + group: deploy-main + cancel-in-progress: false + +jobs: + test: + name: Run Tests + runs-on: x86_64-linux + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + - run: go mod download + - run: go test -v -race -coverprofile=coverage.out ./... + - run: go tool cover -func=coverage.out + + lint: + name: Lint + runs-on: x86_64-linux + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + - run: go vet ./... + - name: Check formatting + run: | + if [ -n "$(gofmt -l .)" ]; then + echo "Go files are not formatted:" + gofmt -l . + exit 1 + fi + - name: Check go.mod tidy + run: | + go mod tidy + if [ -n "$(git diff --name-only go.mod go.sum)" ]; then + echo "go.mod or go.sum is not tidy. Run 'go mod tidy' and commit the changes." + git diff go.mod go.sum + exit 1 + fi + - name: golangci-lint + uses: golangci/golangci-lint-action@v7 + with: + version: latest + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + - name: Run govulncheck + run: govulncheck ./... + + deploy: + needs: [test, lint] + runs-on: debian-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Go + uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + + - name: Build Go binaries + run: | + CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o ./bin/cairn-server ./cmd/cairn-server + CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o ./bin/cairn ./cmd/cairn + + - name: Install Docker CLI + run: | + apt-get update && apt-get install -y curl + curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.5.1.tgz \ + | tar xz --strip-components=1 -C /usr/local/bin docker/docker + + - name: Wait for Docker + run: | + timeout=30 + elapsed=0 + while ! docker info >/dev/null 2>&1; do + [ $elapsed -ge $timeout ] && echo "Docker not ready" && exit 1 + sleep 2 + elapsed=$((elapsed + 2)) + done + + - name: Build image + run: | + REGISTRY="registry.ts.mattnite.net" + docker build -t "${REGISTRY}/cairn:${GITHUB_SHA}" -t "${REGISTRY}/cairn:latest" . + + - name: Push image + run: | + REGISTRY="registry.ts.mattnite.net" + docker push "${REGISTRY}/cairn:${GITHUB_SHA}" + docker push "${REGISTRY}/cairn:latest" + + - name: Update infra + uses: https://git.ts.mattnite.net/mattnite/infra/actions/update-image@main + with: + updates: | + cairn ${{ github.sha }} cairn/cairn.hcl + forgejo_token: ${{ secrets.INFRA_API_TOKEN }} diff --git a/.forgejo/workflows/test.yml b/.forgejo/workflows/test.yml new file mode 100644 index 0000000..854ea67 --- /dev/null +++ b/.forgejo/workflows/test.yml @@ -0,0 +1,82 @@ +name: Test + +on: + pull_request: + branches: + - main + - master + +jobs: + test: + name: Run Tests + runs-on: x86_64-linux + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + - run: go mod download + - run: go test -v -race -coverprofile=coverage.out ./... + - run: go tool cover -func=coverage.out + + lint: + name: Lint + runs-on: x86_64-linux + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + - run: go vet ./... + - name: Check formatting + run: | + if [ -n "$(gofmt -l .)" ]; then + echo "Go files are not formatted:" + gofmt -l . + exit 1 + fi + - name: Check go.mod tidy + run: | + go mod tidy + if [ -n "$(git diff --name-only go.mod go.sum)" ]; then + echo "go.mod or go.sum is not tidy. Run 'go mod tidy' and commit the changes." + git diff go.mod go.sum + exit 1 + fi + - name: golangci-lint + uses: golangci/golangci-lint-action@v7 + with: + version: latest + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + - name: Run govulncheck + run: govulncheck ./... + + build: + name: Build + runs-on: debian-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version: "1.25.3" + - name: Build Go binaries + run: | + CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o ./bin/cairn-server ./cmd/cairn-server + CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o ./bin/cairn ./cmd/cairn + - name: Install Docker CLI + run: | + apt-get update && apt-get install -y curl + curl -fsSL https://download.docker.com/linux/static/stable/x86_64/docker-27.5.1.tgz \ + | tar xz --strip-components=1 -C /usr/local/bin docker/docker + - name: Wait for Docker + run: | + timeout=30 + elapsed=0 + while ! docker info >/dev/null 2>&1; do + [ $elapsed -ge $timeout ] && echo "Docker not ready" && exit 1 + sleep 2 + elapsed=$((elapsed + 2)) + done + - name: Build Docker image + run: docker build -t cairn:test . diff --git a/cmd/cairn/main.go b/cmd/cairn/main.go index 9b7b378..e638ebb 100644 --- a/cmd/cairn/main.go +++ b/cmd/cairn/main.go @@ -68,6 +68,7 @@ Upload flags: -file PATH Path to artifact file (required) -crash-message MSG Crash message (optional) -stack-trace TRACE Stack trace text (optional) + -seed VALUE Simulation seed for reproducibility (optional, stored in metadata) `) } @@ -81,6 +82,7 @@ func cmdUpload(args []string) error { filePath string crashMessage string stackTrace string + seed string ) for i := 0; i < len(args); i++ { @@ -109,6 +111,9 @@ func cmdUpload(args []string) error { case "-stack-trace": i++ stackTrace = args[i] + case "-seed": + i++ + seed = args[i] default: return fmt.Errorf("unknown flag: %s", args[i]) } @@ -130,6 +135,9 @@ func cmdUpload(args []string) error { if stackTrace != "" { meta["stack_trace"] = stackTrace } + if seed != "" { + meta["metadata"] = map[string]any{"seed": seed} + } metaJSON, err := json.Marshal(meta) if err != nil {