Add GoReleaser configuration, CI workflows, and contributing guidelines; update .gitignore and Makefile
This commit is contained in:
80
.github/workflows/main.yml
vendored
Normal file
80
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
name: Build and test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: make build-ci
|
||||||
|
|
||||||
|
lint:
|
||||||
|
name: Lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
uses: golangci/golangci-lint-action@v6
|
||||||
|
with:
|
||||||
|
install-mode: goinstall
|
||||||
|
version: v1.64.8
|
||||||
|
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Install Linux dependencies
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y bubblewrap socat
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: make test-ci
|
||||||
57
.github/workflows/release.yml
vendored
Normal file
57
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
run-name: "Release ${{ github.ref_name }}"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write # Required for SLSA
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
hashes: ${{ steps.hash.outputs.hashes }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: true
|
||||||
|
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v6
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: "~> v2"
|
||||||
|
args: release --clean
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Generate hashes for provenance
|
||||||
|
id: hash
|
||||||
|
run: |
|
||||||
|
cd dist
|
||||||
|
echo "hashes=$(sha256sum * | grep -v checksums.txt | base64 -w0)" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
provenance:
|
||||||
|
needs: [goreleaser]
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
id-token: write
|
||||||
|
contents: write
|
||||||
|
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
||||||
|
with:
|
||||||
|
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
|
||||||
|
upload-assets: true
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,7 @@
|
|||||||
# Binary (only at root, not cmd/fence or pkg/fence)
|
# Binary (only at root, not cmd/fence or pkg/fence)
|
||||||
/fence
|
/fence
|
||||||
|
/fence_unix
|
||||||
|
/fence_darwin
|
||||||
|
|
||||||
# OS files
|
# OS files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
@@ -15,3 +17,6 @@ Thumbs.db
|
|||||||
*.test
|
*.test
|
||||||
coverage.out
|
coverage.out
|
||||||
|
|
||||||
|
# GoReleaser
|
||||||
|
/dist/
|
||||||
|
|
||||||
|
|||||||
41
.golangci.yml
Normal file
41
.golangci.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
modules-download-mode: readonly
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- prefix(github.com/Use-Tusk/fence)
|
||||||
|
gofmt:
|
||||||
|
simplify: true
|
||||||
|
goimports:
|
||||||
|
local-prefixes: github.com/Use-Tusk/fence
|
||||||
|
gocritic:
|
||||||
|
disabled-checks:
|
||||||
|
- singleCaseSwitch
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
- name: exported
|
||||||
|
disabled: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable-all: false
|
||||||
|
disable-all: true
|
||||||
|
enable:
|
||||||
|
- staticcheck
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- unused
|
||||||
|
- ineffassign
|
||||||
|
- gosec
|
||||||
|
- gocritic
|
||||||
|
- revive
|
||||||
|
- gofumpt
|
||||||
|
- misspell
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-use-default: false
|
||||||
|
|
||||||
83
.goreleaser.yaml
Normal file
83
.goreleaser.yaml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
- go mod tidy
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
- -X main.version={{.Version}}
|
||||||
|
- -X main.buildTime={{.Date}}
|
||||||
|
- -X main.gitCommit={{.Commit}}
|
||||||
|
binary: fence
|
||||||
|
main: ./cmd/fence
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- formats: [tar.gz]
|
||||||
|
name_template: >-
|
||||||
|
{{ .ProjectName }}_
|
||||||
|
{{- .Version }}_
|
||||||
|
{{- title .Os }}_
|
||||||
|
{{- if eq .Arch "amd64" }}x86_64
|
||||||
|
{{- else if eq .Arch "386" }}i386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
- LICENSE
|
||||||
|
- ARCHITECTURE.md
|
||||||
|
- CONTRIBUTING.md
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
use: github
|
||||||
|
format: "{{ .SHA }}: {{ .Message }}{{ with .AuthorUsername }} (@{{ . }}){{ end }}"
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^test:"
|
||||||
|
- "^test\\("
|
||||||
|
- "^chore: update$"
|
||||||
|
- "^chore: docs$"
|
||||||
|
- "^docs: update$"
|
||||||
|
- "^chore: typo$"
|
||||||
|
- "^chore\\(deps\\): "
|
||||||
|
- "^(build|ci): "
|
||||||
|
- "merge conflict"
|
||||||
|
- Merge pull request
|
||||||
|
- Merge remote-tracking branch
|
||||||
|
- Merge branch
|
||||||
|
- go mod tidy
|
||||||
|
groups:
|
||||||
|
- title: "New Features"
|
||||||
|
regexp: '^.*?feat(\(.+\))??!?:.+$'
|
||||||
|
order: 100
|
||||||
|
- title: "Security updates"
|
||||||
|
regexp: '^.*?sec(\(.+\))??!?:.+$'
|
||||||
|
order: 150
|
||||||
|
- title: "Bug fixes"
|
||||||
|
regexp: '^.*?(fix|refactor)(\(.+\))??!?:.+$'
|
||||||
|
order: 200
|
||||||
|
- title: "Documentation updates"
|
||||||
|
regexp: ^.*?docs?(\(.+\))??!?:.+$
|
||||||
|
order: 400
|
||||||
|
- title: Other work
|
||||||
|
order: 9999
|
||||||
|
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: Use-Tusk
|
||||||
|
name: fence
|
||||||
|
draft: false
|
||||||
|
prerelease: auto
|
||||||
165
CONTRIBUTING.md
Normal file
165
CONTRIBUTING.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Thanks for helping improve `fence`!
|
||||||
|
|
||||||
|
If you have any questions, feel free to open an issue.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
- Requirements:
|
||||||
|
- Go 1.25+
|
||||||
|
- macOS or Linux
|
||||||
|
- Clone and prepare:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/Use-Tusk/fence
|
||||||
|
cd fence
|
||||||
|
make setup # Install deps and lint tools
|
||||||
|
make build # Build the binary
|
||||||
|
./fence --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dev workflow
|
||||||
|
|
||||||
|
Common targets:
|
||||||
|
|
||||||
|
| Command | Description |
|
||||||
|
|---------|-------------|
|
||||||
|
| `make build` | Build the binary (`./fence`) |
|
||||||
|
| `make run` | Build and run |
|
||||||
|
| `make test` | Run tests |
|
||||||
|
| `make test-ci` | Run tests with coverage |
|
||||||
|
| `make deps` | Download/tidy modules |
|
||||||
|
| `make fmt` | Format code with gofumpt |
|
||||||
|
| `make lint` | Run golangci-lint |
|
||||||
|
| `make build-ci` | Build with version info (used in CI) |
|
||||||
|
| `make help` | Show all available targets |
|
||||||
|
|
||||||
|
## Code structure
|
||||||
|
|
||||||
|
See [ARCHITECTURE.md](ARCHITECTURE.md) for the full project structure and component details.
|
||||||
|
|
||||||
|
## Style and conventions
|
||||||
|
|
||||||
|
- Keep edits focused and covered by tests where possible.
|
||||||
|
- Update [ARCHITECTURE.md](ARCHITECTURE.md) when adding features or changing behavior.
|
||||||
|
- Prefer small, reviewable PRs with a clear rationale.
|
||||||
|
- Run `make fmt` and `make lint` before committing.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
make test
|
||||||
|
|
||||||
|
# Run with verbose output
|
||||||
|
go test -v ./...
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
make test-ci
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing on macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test blocked network request
|
||||||
|
./fence curl https://example.com
|
||||||
|
|
||||||
|
# Test with allowed domain
|
||||||
|
echo '{"network":{"allowedDomains":["example.com"]}}' > /tmp/test.json
|
||||||
|
./fence -s /tmp/test.json curl https://example.com
|
||||||
|
|
||||||
|
# Test monitor mode
|
||||||
|
./fence -m -c "touch /etc/test"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing on Linux
|
||||||
|
|
||||||
|
Requires `bubblewrap` and `socat`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ubuntu/Debian
|
||||||
|
sudo apt install bubblewrap socat
|
||||||
|
|
||||||
|
# Test in Colima or VM
|
||||||
|
./fence curl https://example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**"command not found" after go install:**
|
||||||
|
|
||||||
|
- Add `$GOPATH/bin` to your PATH
|
||||||
|
- Or use `go env GOPATH` to find the path
|
||||||
|
|
||||||
|
**Module issues:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go mod tidy # Clean up dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
**Build cache issues:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go clean -cache
|
||||||
|
go clean -modcache
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS sandbox issues:**
|
||||||
|
|
||||||
|
- Check `log stream --predicate 'eventMessage ENDSWITH "_SBX"'` for violations
|
||||||
|
- Ensure you're not running as root
|
||||||
|
|
||||||
|
**Linux bwrap issues:**
|
||||||
|
|
||||||
|
- May need `sudo` or `kernel.unprivileged_userns_clone=1`
|
||||||
|
- Check that socat and bwrap are installed
|
||||||
|
|
||||||
|
## For Maintainers
|
||||||
|
|
||||||
|
### Releasing
|
||||||
|
|
||||||
|
Releases are automated using [GoReleaser](https://goreleaser.com/) via GitHub Actions.
|
||||||
|
|
||||||
|
#### Creating a release
|
||||||
|
|
||||||
|
1. Tag the commit with a semantic version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git tag v1.0.0
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
2. GitHub Actions will automatically:
|
||||||
|
- Build binaries for all supported platforms
|
||||||
|
- Create archives with README, LICENSE, and ARCHITECTURE.md
|
||||||
|
- Generate checksums
|
||||||
|
- Create a GitHub release with changelog
|
||||||
|
- Upload all artifacts
|
||||||
|
|
||||||
|
#### Supported platforms
|
||||||
|
|
||||||
|
The release workflow builds for:
|
||||||
|
|
||||||
|
- **Linux**: amd64, arm64
|
||||||
|
- **macOS (darwin)**: amd64, arm64
|
||||||
|
|
||||||
|
#### Building locally for distribution
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for current platform
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Cross-compile
|
||||||
|
make build-linux
|
||||||
|
make build-darwin
|
||||||
|
|
||||||
|
# With version info (mimics CI builds)
|
||||||
|
make build-ci
|
||||||
|
```
|
||||||
|
|
||||||
|
To test the GoReleaser configuration locally:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
goreleaser release --snapshot --clean
|
||||||
|
```
|
||||||
103
Makefile
Normal file
103
Makefile
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
GOCMD=go
|
||||||
|
GOBUILD=$(GOCMD) build
|
||||||
|
GOCLEAN=$(GOCMD) clean
|
||||||
|
GOTEST=$(GOCMD) test
|
||||||
|
GOMOD=$(GOCMD) mod
|
||||||
|
BINARY_NAME=fence
|
||||||
|
BINARY_UNIX=$(BINARY_NAME)_unix
|
||||||
|
|
||||||
|
.PHONY: all build build-ci build-linux test test-ci clean deps install-lint-tools setup setup-ci run fmt lint release release-minor help
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
@echo "🔨 Building $(BINARY_NAME)..."
|
||||||
|
$(GOBUILD) -o $(BINARY_NAME) -v ./cmd/fence
|
||||||
|
|
||||||
|
build-ci:
|
||||||
|
@echo "🏗️ CI: Building $(BINARY_NAME) with version info..."
|
||||||
|
$(eval VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev"))
|
||||||
|
$(eval BUILD_TIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ'))
|
||||||
|
$(eval GIT_COMMIT := $(shell git rev-parse HEAD 2>/dev/null || echo "unknown"))
|
||||||
|
$(GOBUILD) -ldflags "-s -w -X main.version=$(VERSION) -X main.buildTime=$(BUILD_TIME) -X main.gitCommit=$(GIT_COMMIT)" -o $(BINARY_NAME) -v ./cmd/fence
|
||||||
|
|
||||||
|
test:
|
||||||
|
@echo "🧪 Running tests..."
|
||||||
|
$(GOTEST) -v ./...
|
||||||
|
|
||||||
|
test-ci:
|
||||||
|
@echo "🧪 CI: Running tests with coverage..."
|
||||||
|
$(GOTEST) -v -race -coverprofile=coverage.out ./...
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo "🧹 Cleaning..."
|
||||||
|
$(GOCLEAN)
|
||||||
|
rm -f $(BINARY_NAME)
|
||||||
|
rm -f $(BINARY_UNIX)
|
||||||
|
rm -f coverage.out
|
||||||
|
|
||||||
|
deps:
|
||||||
|
@echo "📦 Downloading dependencies..."
|
||||||
|
$(GOMOD) download
|
||||||
|
$(GOMOD) tidy
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
@echo "🐧 Building for Linux..."
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINARY_UNIX) -v ./cmd/fence
|
||||||
|
|
||||||
|
build-darwin:
|
||||||
|
@echo "🍎 Building for macOS..."
|
||||||
|
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 $(GOBUILD) -o $(BINARY_NAME)_darwin -v ./cmd/fence
|
||||||
|
|
||||||
|
install-lint-tools:
|
||||||
|
@echo "📦 Installing linting tools..."
|
||||||
|
go install mvdan.cc/gofumpt@latest
|
||||||
|
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||||
|
@echo "✅ Linting tools installed"
|
||||||
|
|
||||||
|
setup: deps install-lint-tools
|
||||||
|
@echo "✅ Development environment ready"
|
||||||
|
|
||||||
|
setup-ci: deps install-lint-tools
|
||||||
|
@echo "✅ CI environment ready"
|
||||||
|
|
||||||
|
run: build
|
||||||
|
./$(BINARY_NAME)
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
@echo "📝 Formatting code..."
|
||||||
|
gofumpt -w .
|
||||||
|
|
||||||
|
lint:
|
||||||
|
@echo "🔍 Linting code..."
|
||||||
|
golangci-lint run --allow-parallel-runners
|
||||||
|
|
||||||
|
release:
|
||||||
|
@echo "🚀 Creating patch release..."
|
||||||
|
./scripts/release.sh patch
|
||||||
|
|
||||||
|
release-minor:
|
||||||
|
@echo "🚀 Creating minor release..."
|
||||||
|
./scripts/release.sh minor
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Available targets:"
|
||||||
|
@echo " all - build (default)"
|
||||||
|
@echo " build - Build the binary"
|
||||||
|
@echo " build-ci - Build for CI with version info"
|
||||||
|
@echo " build-linux - Build for Linux"
|
||||||
|
@echo " build-darwin - Build for macOS"
|
||||||
|
@echo " test - Run tests"
|
||||||
|
@echo " test-ci - Run tests for CI with coverage"
|
||||||
|
@echo " clean - Clean build artifacts"
|
||||||
|
@echo " deps - Download dependencies"
|
||||||
|
@echo " install-lint-tools - Install linting tools"
|
||||||
|
@echo " setup - Setup development environment"
|
||||||
|
@echo " setup-ci - Setup CI environment"
|
||||||
|
@echo " run - Build and run"
|
||||||
|
@echo " fmt - Format code"
|
||||||
|
@echo " lint - Lint code"
|
||||||
|
@echo " release - Create patch release (v0.0.X)"
|
||||||
|
@echo " release-minor - Create minor release (v0.X.0)"
|
||||||
|
@echo " help - Show this help"
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ func parseViolation(line string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter out noisy violations
|
// Filter out noisy violations
|
||||||
if isNoisyViolation(operation, details) {
|
if isNoisyViolation(details) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ func shouldShowViolation(operation string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// isNoisyViolation returns true if this violation is system noise that should be filtered.
|
// isNoisyViolation returns true if this violation is system noise that should be filtered.
|
||||||
func isNoisyViolation(operation, details string) bool {
|
func isNoisyViolation(details string) bool {
|
||||||
// Filter out TTY/terminal writes (very noisy from any process that prints output)
|
// Filter out TTY/terminal writes (very noisy from any process that prints output)
|
||||||
if strings.HasPrefix(details, "/dev/tty") ||
|
if strings.HasPrefix(details, "/dev/tty") ||
|
||||||
strings.HasPrefix(details, "/dev/pts") {
|
strings.HasPrefix(details, "/dev/pts") {
|
||||||
@@ -195,4 +195,3 @@ func isNoisyViolation(operation, details string) bool {
|
|||||||
func GetSessionSuffix() string {
|
func GetSessionSuffix() string {
|
||||||
return sessionSuffix // defined in macos.go
|
return sessionSuffix // defined in macos.go
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
153
scripts/release.sh
Executable file
153
scripts/release.sh
Executable file
@@ -0,0 +1,153 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Usage: ./scripts/release.sh [patch|minor]
|
||||||
|
# Default: patch
|
||||||
|
|
||||||
|
BUMP_TYPE="${1:-patch}"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
|
||||||
|
|
||||||
|
# Validate bump type
|
||||||
|
if [[ "$BUMP_TYPE" != "patch" && "$BUMP_TYPE" != "minor" ]]; then
|
||||||
|
error "Invalid bump type: $BUMP_TYPE. Use 'patch' or 'minor' (or no argument for minor)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Bump type: $BUMP_TYPE"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Preflight checks
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
info "Running preflight checks..."
|
||||||
|
|
||||||
|
# Check we're in a git repository
|
||||||
|
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
|
||||||
|
error "Not in a git repository"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check we're on the default branch (main)
|
||||||
|
DEFAULT_BRANCH="main"
|
||||||
|
CURRENT_BRANCH=$(git branch --show-current)
|
||||||
|
if [[ "$CURRENT_BRANCH" != "$DEFAULT_BRANCH" ]]; then
|
||||||
|
error "Not on default branch. Current: $CURRENT_BRANCH, Expected: $DEFAULT_BRANCH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for uncommitted changes
|
||||||
|
if ! git diff --quiet || ! git diff --staged --quiet; then
|
||||||
|
error "Working directory has uncommitted changes. Commit or stash them first."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for untracked files (warning only)
|
||||||
|
UNTRACKED=$(git ls-files --others --exclude-standard)
|
||||||
|
if [[ -n "$UNTRACKED" ]]; then
|
||||||
|
warn "Untracked files present (continuing anyway):"
|
||||||
|
echo "$UNTRACKED" | head -5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fetch latest from remote
|
||||||
|
info "Fetching latest from origin..."
|
||||||
|
git fetch origin "$DEFAULT_BRANCH" --tags
|
||||||
|
|
||||||
|
# Check if local branch is up to date with remote
|
||||||
|
LOCAL_COMMIT=$(git rev-parse HEAD)
|
||||||
|
REMOTE_COMMIT=$(git rev-parse "origin/$DEFAULT_BRANCH")
|
||||||
|
if [[ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]]; then
|
||||||
|
error "Local branch is not up to date with origin/$DEFAULT_BRANCH. Run 'git pull' first."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if there are commits since last tag
|
||||||
|
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
|
||||||
|
if [[ -n "$LAST_TAG" ]]; then
|
||||||
|
COMMITS_SINCE_TAG=$(git rev-list "$LAST_TAG"..HEAD --count)
|
||||||
|
if [[ "$COMMITS_SINCE_TAG" -eq 0 ]]; then
|
||||||
|
error "No commits since last tag ($LAST_TAG). Nothing to release."
|
||||||
|
fi
|
||||||
|
info "Commits since $LAST_TAG: $COMMITS_SINCE_TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that tests pass
|
||||||
|
info "Running tests..."
|
||||||
|
if ! make test-ci; then
|
||||||
|
error "Tests failed. Fix them before releasing."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that lint passes
|
||||||
|
info "Running linter..."
|
||||||
|
if ! make lint; then
|
||||||
|
error "Lint failed. Fix issues before releasing."
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "✓ All preflight checks passed"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Calculate new version
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
if [[ -z "$LAST_TAG" ]]; then
|
||||||
|
# No existing tags, start at v0.1.0
|
||||||
|
NEW_VERSION="v0.1.0"
|
||||||
|
info "No existing tags found. Starting at $NEW_VERSION"
|
||||||
|
else
|
||||||
|
# Parse current version (strip 'v' prefix)
|
||||||
|
VERSION="${LAST_TAG#v}"
|
||||||
|
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
|
||||||
|
|
||||||
|
# Validate parsed version
|
||||||
|
if [[ -z "$MAJOR" || -z "$MINOR" || -z "$PATCH" ]]; then
|
||||||
|
error "Failed to parse version from tag: $LAST_TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increment based on bump type
|
||||||
|
case "$BUMP_TYPE" in
|
||||||
|
patch)
|
||||||
|
PATCH=$((PATCH + 1))
|
||||||
|
;;
|
||||||
|
minor)
|
||||||
|
MINOR=$((MINOR + 1))
|
||||||
|
PATCH=0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||||
|
info "Version bump: $LAST_TAG → $NEW_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Confirm and create tag
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " Ready to release: $NEW_VERSION"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
read -p "Create and push tag $NEW_VERSION? [y/N] " -n 1 -r
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
info "Aborted."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create annotated tag
|
||||||
|
info "Creating tag $NEW_VERSION..."
|
||||||
|
git tag -a "$NEW_VERSION" -m "Release $NEW_VERSION"
|
||||||
|
|
||||||
|
# Push tag to origin
|
||||||
|
info "Pushing tag to origin..."
|
||||||
|
git push origin "$NEW_VERSION"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
info "✓ Released $NEW_VERSION"
|
||||||
|
info "GitHub Actions will now build and publish the release."
|
||||||
|
info "Watch progress at: https://github.com/Use-Tusk/fence/actions"
|
||||||
Reference in New Issue
Block a user