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
125 changes: 65 additions & 60 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,76 +5,81 @@ on:
push:
branches: [master, main]

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up mise
uses: jdx/mise-action@v2

- name: Install test dependencies
run: |
sudo apt-get update
sudo apt-get install -y shellcheck

- name: Static checks
run: |
bash -n scripts/start-issue
shellcheck install.sh scripts/start-issue scripts/build-start-issue scripts/bump-version scripts/prepare-release scripts/lib/start_issue/*.sh
git diff --check
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: make test
- run: make build
- run: .build/start-issue --version

- name: Legacy environment drift check
run: |
legacy_name="CLAUDE""_WORKTREE_DIR"
if grep -R --line-number "$legacy_name" scripts README.md README.ru.md docs doc test .github; then
echo "Legacy Claude worktree environment variable name must not be used."
exit 1
fi

- name: Integration tests
run: mise exec -- bats test
sandbox-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: make e2e-sandbox

install-script:
runs-on: ${{ matrix.os }}
platform-smoke:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]

include:
- runner: ubuntu-latest
artifact: start-issue
- runner: macos-latest
artifact: start-issue
- runner: windows-latest
artifact: start-issue.exe
runs-on: ${{ matrix.runner }}
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Build local release artifact
run: |
bash scripts/build-start-issue "$RUNNER_TEMP/start-issue" >/dev/null
chmod +x "$RUNNER_TEMP/start-issue"

- name: Generate checksum file
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: go build -o ${{ matrix.artifact }} ./cmd/start-issue
- if: runner.os != 'Windows'
run: ./${{ matrix.artifact }} --version
- if: runner.os != 'Windows'
run: make test
- if: runner.os == 'Windows'
shell: pwsh
run: |
if command -v sha256sum >/dev/null 2>&1; then
checksum="$(sha256sum "$RUNNER_TEMP/start-issue" | awk '{ print $1 }')"
else
checksum="$(shasum -a 256 "$RUNNER_TEMP/start-issue" | awk '{ print $1 }')"
fi
printf '%s %s\n' "$checksum" start-issue > "$RUNNER_TEMP/start-issue.sha256"
& .\${{ matrix.artifact }} --version
$update = (go run ./cmd/start-issue update | Out-String)
if ($update -notmatch 'Windows update is manual') { throw "Expected Windows manual-update instruction: $update" }

- name: Test install.sh via pipe
run: |
curl -fsSL "file://$GITHUB_WORKSPACE/install.sh" | env \
PREFIX="$RUNNER_TEMP/prefix" \
START_ISSUE_ASSET_URL="file://$RUNNER_TEMP/start-issue" \
START_ISSUE_CHECKSUM_URL="file://$RUNNER_TEMP/start-issue.sha256" \
bash

- name: Verify installed binary
run: |
test -x "$RUNNER_TEMP/prefix/bin/start-issue"
"$RUNNER_TEMP/prefix/bin/start-issue" --version | grep '^start-issue v'
cross-build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: darwin
arch: amd64
- os: darwin
arch: arm64
- os: windows
arch: amd64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: go build ./cmd/start-issue
env:
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
58 changes: 19 additions & 39 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,31 @@ name: Release

on:
push:
tags:
- "v*"
tags: ["v*"]

permissions:
contents: write

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
release:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up mise
uses: jdx/mise-action@v2

- name: Install test dependencies
run: |
sudo apt-get update
sudo apt-get install -y shellcheck

- name: Verify tag matches script version
run: |
script_version="$(awk -F'"' '/^VERSION="/ { print $2; exit }' scripts/start-issue)"
tag_version="${GITHUB_REF_NAME#v}"
test "$script_version" = "$tag_version"

- name: Run checks
run: make test

- name: Build release artifact
run: |
make build
cp .build/start-issue start-issue
sha256sum start-issue > start-issue.sha256

- name: Publish GitHub release
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: make test
- run: make e2e-sandbox
- uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: ~> v2
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish release
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
start-issue \
start-issue.sha256 \
--generate-notes
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "$GITHUB_REF_NAME" --draft=false
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.build/
/start-issue
/start-issue.exe
38 changes: 38 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 2
project_name: start-issue

before:
hooks:
- go mod tidy
- sh -c 'mkdir -p .release && cp scripts/v1-upgrade-shim .release/start-issue && chmod 0755 .release/start-issue && (cd .release && sha256sum start-issue > start-issue.sha256)'

builds:
- id: start-issue
main: ./cmd/start-issue
binary: start-issue
env: [CGO_ENABLED=0]
goos: [linux, darwin, windows]
goarch: [amd64, arm64]
ignore:
- goos: windows
goarch: arm64
ldflags:
- -s -w -X main.version={{ .Version }}

archives:
- id: binaries
formats: [binary]
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"

checksum:
name_template: checksums.txt

release:
# Keep the release invisible until GoReleaser has uploaded both the normal
# assets and the v1 bridge required by older self-updaters.
draft: true
extra_files:
- glob: .release/start-issue
name_template: start-issue
- glob: .release/start-issue.sha256
name_template: start-issue.sha256
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ This project follows Semantic Versioning.

- Removed the obsolete `codex exec --ask-for-approval` argument from the Codex human-gate workflow, restoring compatibility with current Codex CLI versions.

## [2.0.0] - 2026-07-22

### Changed

- Replaced the Bash CLI, Bats suite, and shell build/release tooling with the Go implementation and Go test suite.
- Changed distribution to platform-specific Go binaries with `checksums.txt` verification.

## [1.13.2] - 2026-07-19

### Added
Expand Down
54 changes: 19 additions & 35 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,57 +1,41 @@
.PHONY: build install uninstall test e2e-human-gate print-version bump-patch bump-minor bump-major release-patch release-minor release-major
.PHONY: build install uninstall test e2e-sandbox e2e-human-gate print-version bump-patch bump-minor bump-major release-patch release-minor release-major

PREFIX ?= $(HOME)/.local
BINDIR ?= $(PREFIX)/bin
BUILD_DIR ?= .build
BUILD_OUTPUT ?= $(BUILD_DIR)/start-issue
# Release tags are the version source. A checkout between releases carries the
# nearest tag plus its Git describe suffix, which keeps source builds distinct
# from the last published release for update comparisons.
VERSION ?= $(shell git describe --tags --match 'v[0-9]*' --always --dirty 2>/dev/null | sed 's/^v//')
VERSION := $(if $(strip $(VERSION)),$(VERSION),dev)

build:
@mkdir -p "$(BUILD_DIR)"
@bash scripts/build-start-issue "$(BUILD_OUTPUT)" >/dev/null
@chmod +x "$(BUILD_OUTPUT)"
go build -trimpath -ldflags "-s -w -X main.version=$(VERSION)" -o "$(BUILD_OUTPUT)" ./cmd/start-issue
@echo "Built: $(BUILD_OUTPUT)"

install:
install: build
@mkdir -p "$(BINDIR)"
@set -e; \
tmpfile="$$(mktemp)"; \
trap 'rm -f "$$tmpfile"' EXIT; \
bash scripts/build-start-issue "$$tmpfile" >/dev/null; \
cp "$$tmpfile" "$(BINDIR)/start-issue"
@chmod +x "$(BINDIR)/start-issue"
install -m 0755 "$(BUILD_OUTPUT)" "$(BINDIR)/start-issue"
@echo "Installed: $(BINDIR)/start-issue"

uninstall:
@rm -f "$(BINDIR)/start-issue"
rm -f "$(BINDIR)/start-issue"
@echo "Removed: $(BINDIR)/start-issue"

test:
bash -n scripts/start-issue
shellcheck install.sh scripts/start-issue scripts/build-start-issue scripts/bump-version scripts/prepare-release scripts/lib/start_issue/*.sh test/e2e/*.sh
@test -z "$$($$(go env GOROOT)/bin/gofmt -l cmd)"
go vet ./...
go test ./...
python3 scripts/check_memory_bank_index.py --max-depth 4
git diff --check
bats test

e2e-human-gate:
@bash test/e2e/human-gate.sh
e2e-human-gate: build
@START_ISSUE_E2E_BINARY="$(abspath $(BUILD_OUTPUT))" bash test/e2e/human-gate.sh

print-version:
@awk -F'"' '/^VERSION="/ { print $$2; exit }' scripts/start-issue

bump-patch:
@bash scripts/bump-version patch

bump-minor:
@bash scripts/bump-version minor

bump-major:
@bash scripts/bump-version major
e2e-sandbox: build
@START_ISSUE_SANDBOX_BINARY="$(abspath $(BUILD_OUTPUT))" bash test/e2e/sandbox.sh

release-patch:
@bash scripts/prepare-release patch

release-minor:
@bash scripts/prepare-release minor

release-major:
@bash scripts/prepare-release major
print-version:
@echo "$(VERSION)"
Loading
Loading