Taskfile.yaml

  1# https://taskfile.dev
  2
  3version: "3"
  4
  5vars:
  6  VERSION:
  7    sh: git describe --long 2>/dev/null || echo ""
  8  RACE:
  9    sh: test -f race.log && echo "1" || echo ""
 10
 11env:
 12  CGO_ENABLED: 0
 13  GOEXPERIMENT: greenteagc
 14
 15tasks:
 16  lint:install:
 17    desc: Install golangci-lint
 18    cmds:
 19      - go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
 20    env:
 21      GOTOOLCHAIN: go1.25.0
 22
 23  lint:
 24    desc: Run base linters
 25    cmds:
 26      - task: lint:log
 27      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m
 28    env:
 29      GOEXPERIMENT: null
 30
 31  lint:log:
 32    desc: Check that log messages start with capital letters
 33    cmds:
 34      - ./scripts/check_log_capitalization.sh
 35
 36  lint:fix:
 37    desc: Run base linters and fix issues
 38    cmds:
 39      - golangci-lint run --path-mode=abs --config=".golangci.yml" --timeout=5m --fix
 40    env:
 41      GOEXPERIMENT: null
 42
 43  build:
 44    desc: Run build
 45    vars:
 46      LDFLAGS: '{{if .VERSION}}-ldflags="-X git.secluded.site/crush/internal/version.Version={{.VERSION}}"{{end}}'
 47    cmds:
 48      - "go build {{if .RACE}}-race{{end}} {{.LDFLAGS}} ."
 49    generates:
 50      - crush
 51
 52  run:
 53    desc: Run build
 54    cmds:
 55      - task: build
 56      - "./crush {{.CLI_ARGS}} {{if .RACE}}2>race.log{{end}}"
 57
 58  test:
 59    desc: Run tests
 60    cmds:
 61      - go test -race -failfast ./... {{.CLI_ARGS}}
 62
 63  test:record:
 64    desc: Run tests and record all VCR cassettes again
 65    aliases: [record]
 66    cmds:
 67      - rm -r internal/agent/testdata
 68      - go test -v -count=1 -timeout=1h ./internal/agent
 69
 70  fmt:
 71    desc: Run gofumpt
 72    cmds:
 73      - gofumpt -w .
 74
 75  fmt:html:
 76    desc: Run prettier on HTML/CSS/JS files
 77    cmds:
 78      - prettier --write internal/cmd/stats/index.html internal/cmd/stats/index.css internal/cmd/stats/index.js
 79
 80  dev:
 81    desc: Run with profiling enabled
 82    env:
 83      CRUSH_PROFILE: true
 84    cmds:
 85      - go run .
 86
 87  install:
 88    desc: Install the application
 89    vars:
 90      LDFLAGS: '{{if .VERSION}}-ldflags="-X git.secluded.site/crush/internal/version.Version={{.VERSION}}"{{end}}'
 91    cmds:
 92      - task: fetch-tags
 93      - go install {{.LDFLAGS}} -v .
 94
 95  profile:cpu:
 96    desc: 10s CPU profile
 97    cmds:
 98      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/profile?seconds=10'
 99
100  profile:heap:
101    desc: Heap profile
102    cmds:
103      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/heap'
104
105  profile:allocs:
106    desc: Allocations profile
107    cmds:
108      - go tool pprof -http :6061 'http://localhost:6060/debug/pprof/allocs'
109
110  schema:
111    desc: Generate JSON schema for configuration
112    cmds:
113      - go run main.go schema > schema.json
114      - echo "Generated schema.json"
115    generates:
116      - schema.json
117
118  hyper:
119    desc: Update Hyper embedded provider.json
120    cmds:
121      - go generate ./internal/agent/hyper/...
122    generates:
123      - ./internal/agent/hyper/provider.json
124
125  release:
126    desc: Create and push a new tag following semver
127    vars:
128      NEXT:
129        sh: svu next --always || go run github.com/caarlos0/svu/v3@latest next --always
130    prompt: "This will release {{.NEXT}}. Continue?"
131    preconditions:
132      - sh: '[ $(git symbolic-ref --short HEAD) = "main" ]'
133        msg: Not on main branch
134      - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
135        msg: "Git is dirty"
136      - sh: 'gh run list --workflow build.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
137        msg: "Test build for this commit failed or not present"
138      - sh: 'gh run list --workflow snapshot.yml --commit $(git rev-parse HEAD) --status success --json conclusion -q ".[0].conclusion" | grep -q success'
139        msg: "Snapshot build for this commit failed or not present"
140    cmds:
141      - task: fetch-tags
142      - git commit --allow-empty -m "{{.NEXT}}"
143      - git tag --annotate --sign -m "{{.NEXT}}" {{.NEXT}} {{.CLI_ARGS}}
144      - echo "Pushing {{.NEXT}}..."
145      - git push origin main --follow-tags
146
147  fetch-tags:
148    cmds:
149      - git tag -d nightly || true
150      - git fetch --tags
151
152  deps:
153    desc: Update Fantasy and Catwalk
154    cmds:
155      - go get charm.land/fantasy
156      - go get charm.land/catwalk
157      - go mod tidy
158
159  release:fork:
160    desc: Create and push a fork release tag (combined workflow)
161    cmds:
162      - task: release:fork:tag
163      - task: release:fork:push
164
165  release:fork:tag:
166    desc: Create a fork release tag locally (without pushing)
167    vars:
168      UPSTREAM_VERSION:
169        sh: git tag -l "v*" | sort -V | tail -1 || echo "v0.0.0"
170      EXISTING_FORK_TAGS:
171        sh: git tag -l "{{.UPSTREAM_VERSION}}-fork.*" | wc -l
172      NEXT_NUM:
173        sh: echo $(({{.EXISTING_FORK_TAGS}} + 1))
174      TAG: "{{.UPSTREAM_VERSION}}-fork.{{.NEXT_NUM}}"
175    prompt: "Create fork release {{.TAG}}?"
176    preconditions:
177      - sh: '[ $(git symbolic-ref --short HEAD) = "dev" ]'
178        msg: Not on dev branch
179      - sh: "[ $(git status --porcelain=2 | wc -l) = 0 ]"
180        msg: "Git is dirty"
181    cmds:
182      - git tag -d nightly || true
183      - git fetch upstream --tags
184      - >-
185        crush run "Please update the mentioned version in the top of the README to {{.TAG}}.
186        You only need to read the first 65 lines for the relevant bits.
187        Commit with 'docs(README): bump to [ver]' when you're done."
188      - git show --stat HEAD
189      - defer:
190          task: release:fork:cleanup
191          vars:
192            TAG: "{{.TAG}}"
193      - task: release:fork:confirm
194      - git push soft
195      - git tag -a {{.TAG}}
196      - echo "Tagged {{.TAG}} locally. Run 'task release:fork:push' to push."
197
198  release:fork:push:
199    desc: Push an existing fork release tag and notify module proxy
200    vars:
201      TAG:
202        sh: git describe --tags --abbrev=0 --match "*-fork.*" 2>/dev/null || echo ""
203    preconditions:
204      - sh: '[ -n "{{.TAG}}" ]'
205        msg: "No fork tag found. Run 'task release:fork:tag' first."
206      - sh: 'git tag -l "{{.TAG}}" | grep -q "{{.TAG}}"'
207        msg: "Tag {{.TAG}} does not exist locally"
208    prompt: "Push {{.TAG}} to remote and notify module proxy?"
209    cmds:
210      - git push soft {{.TAG}}
211      - echo "Released {{.TAG}}"
212      - go list -m git.secluded.site/crush@{{.TAG}} > /dev/null
213      - echo "Module proxy notified"
214
215  release:fork:confirm:
216    desc: Review LLM-generated commit and confirm release
217    internal: true
218    prompt: "Proceed with tagging?"
219
220  release:fork:cleanup:
221    desc: Undo LLM commit if release aborted
222    internal: true
223    cmds:
224      - git reset --hard HEAD~1
225      - git tag -d {{.TAG}} 2>/dev/null || true
226    status:
227      - git tag -l {{.TAG}} | grep -q {{.TAG}}