Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"includeCoAuthoredBy": false,
"gitAttribution": false
}
112 changes: 112 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: CI

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

permissions:
contents: read

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Verify dependencies
run: |
cd forge-core && go mod verify
cd ../forge-cli && go mod verify
cd ../forge-plugins && go mod verify

- name: Vet
run: go vet ./forge-core/... ./forge-cli/... ./forge-plugins/...

- name: Check formatting
run: test -z "$(gofmt -l forge-core forge-cli forge-plugins)"

- name: Test
run: go test -race -coverprofile=coverage.out ./forge-core/... ./forge-cli/... ./forge-plugins/...

- name: Check coverage threshold
run: |
COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%')
echo "Total coverage: ${COVERAGE}%"
if (( $(echo "$COVERAGE < 70" | bc -l) )); then
echo "::warning::Coverage ${COVERAGE}% is below 70% threshold"
fi

- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage.out

lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- uses: golangci/golangci-lint-action@v7
with:
version: v2.10.1
args: ./forge-core/... ./forge-cli/... ./forge-plugins/...

integration:
name: Integration Tests
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Integration tests
run: go test -race -tags=integration ./forge-core/... ./forge-cli/... ./forge-plugins/...

build:
name: Build (${{ matrix.goos }}/${{ matrix.goarch }})
runs-on: ubuntu-latest
needs: [test, lint]
strategy:
matrix:
include:
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: darwin
goarch: amd64
- goos: darwin
goarch: arm64
- goos: windows
goarch: amd64
- goos: windows
goarch: arm64
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Build
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: "0"
run: cd forge-cli && go build -ldflags "-s -w" -o ../forge-${{ matrix.goos }}-${{ matrix.goarch }} ./cmd/forge
29 changes: 29 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-go@v5
with:
go-version: "1.25"

- uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Code coverage profiles and other test artifacts
*.out
coverage.*
*.coverprofile
profile.cov

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
# go.work
# go.work.sum

# env file
.env

# Editor/IDE
# .idea/
# .vscode/


# Binary
/forge

# Build output
.forge-output/

# OS files
.DS_Store
44 changes: 44 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
version: 2

builds:
- dir: forge-cli
main: ./cmd/forge
binary: forge
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
ldflags:
- -s -w -X main.version={{.Version}}

archives:
- formats:
- tar.gz
format_overrides:
- goos: windows
formats:
- zip
name_template: "forge-{{ .Os }}-{{ .Arch }}"
replacements:
linux: Linux
darwin: Darwin
windows: Windows
amd64: x86_64 # matches uname -m
arm64: arm64 # matches uname -m

checksum:
name_template: "checksums.txt"

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^ci:"
- "^chore:"
59 changes: 59 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
BINARY := forge
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo none)
LDFLAGS := -s -w -X main.version=$(VERSION) -X main.commit=$(COMMIT)
COVERFILE := coverage.out
MODULES := forge-core forge-cli forge-plugins

.PHONY: build test test-integration vet fmt lint cover cover-html install clean release help

## build: Compile the forge binary
build:
cd forge-cli && go build -ldflags "$(LDFLAGS)" -o ../$(BINARY) ./cmd/forge

## test: Run all unit tests with race detection across all modules
test:
@for mod in $(MODULES); do echo "==> Testing $$mod"; (cd $$mod && go test -race ./...); done

## test-integration: Run integration tests (requires build tag)
test-integration:
@for mod in $(MODULES); do echo "==> Integration testing $$mod"; (cd $$mod && go test -race -tags=integration ./...); done

## vet: Run go vet on all modules
vet:
@for mod in $(MODULES); do echo "==> Vetting $$mod"; (cd $$mod && go vet ./...); done

## fmt: Check that all Go files are gofmt-compliant
fmt:
@test -z "$$(gofmt -l .)" || (echo "Files not formatted:"; gofmt -l .; exit 1)

## lint: Run golangci-lint on all modules (must be installed separately)
lint:
@for mod in $(MODULES); do echo "==> Linting $$mod"; (cd $$mod && golangci-lint run ./...); done

## cover: Generate test coverage report for all modules
cover:
@for mod in $(MODULES); do echo "==> Coverage $$mod"; (cd $$mod && go test -race -coverprofile=$(COVERFILE) ./... && go tool cover -func=$(COVERFILE)); done

## cover-html: Open coverage report in browser (forge-cli)
cover-html:
cd forge-cli && go test -race -coverprofile=$(COVERFILE) ./... && go tool cover -html=$(COVERFILE)

## install: Install forge to GOPATH/bin
install:
cd forge-cli && go install -ldflags "$(LDFLAGS)" ./cmd/forge

## clean: Remove build artifacts and coverage files
clean:
rm -f $(BINARY)
@for mod in $(MODULES); do rm -f $$mod/$(COVERFILE); done

## release: Build a snapshot release using goreleaser
release:
goreleaser release --snapshot --clean

## help: Show this help message
help:
@echo "Usage: make [target]"
@echo ""
@sed -n 's/^## //p' $(MAKEFILE_LIST) | column -t -s ':'
Loading
Loading