Skip to content
Merged

dev #14

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d2b7d37
ci: added GHA workflows
jamesjohnsdev Jun 17, 2026
153e150
ci: dependabot
jamesjohnsdev Jun 17, 2026
2ae962d
chore: add codeowners
jamesjohnsdev Jun 17, 2026
88f81da
feat: added command
jamesjohnsdev Jun 17, 2026
f6233a9
doc: updated readme
jamesjohnsdev Jun 17, 2026
84ce84d
feat: added `complete` command
jamesjohnsdev Jun 17, 2026
bda3718
feat: enabled creation direct passthrough to editor
jamesjohnsdev Jun 17, 2026
bd486a1
refactor: rename complete => close to match GH terminology
jamesjohnsdev Jun 17, 2026
a7c1203
feat: improved display for issue list
jamesjohnsdev Jun 17, 2026
722a30b
fix: correct parsing of local issue numbers
jamesjohnsdev Jun 17, 2026
1b9e74c
test: test suites added
jamesjohnsdev Jun 17, 2026
2530941
test: added fuzz testing
jamesjohnsdev Jun 17, 2026
7d1b73b
chore: cleanup old references to `issue` command rather than `issues`
jamesjohnsdev Jun 17, 2026
7d9de9b
feat: delete command
jamesjohnsdev Jun 18, 2026
440fd43
ci: fix main CI workflow
jamesjohnsdev Jun 18, 2026
abd6765
chore: formating and unchecked errs
jamesjohnsdev Jun 18, 2026
c2e3b8a
fix(root): rename root command name to "issues"
jamesjohnsdev Jun 18, 2026
5328d2f
ci: point dependabot at root go module
jamesjohnsdev Jun 18, 2026
257228c
fix(util): reject partial numeric ids such as "123abc"
jamesjohnsdev Jun 18, 2026
5869e48
fix(create): three editor mode correctness bugs
jamesjohnsdev Jun 18, 2026
5f90b97
fix(view): split editor string to support flags
jamesjohnsdev Jun 18, 2026
32b811e
test(fuzz): skip round-trip body check for leading-newline inputs
jamesjohnsdev Jun 18, 2026
5f3127e
chore: mod tidy
jamesjohnsdev Jun 18, 2026
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @jamesjohnsdev
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
day: "saturday"
time: "03:00"
timezone: "UTC"
cooldown:
default-days: 7
groups:
go-dependencies:
patterns:
- "*"
open-pull-requests-limit: 3

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "saturday"
time: "03:00"
timezone: "UTC"
cooldown:
default-days: 7
groups:
github-actions:
patterns:
- "*"
open-pull-requests-limit: 3
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: CI

permissions:
contents: read

on:
pull_request:
branches: [main]

jobs:
build:
name: Build
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
with:
go-version-file: go.mod
cache-dependency-path: go.sum

- name: golangci-lint
uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9

- name: govulncheck
run: go run golang.org/x/vuln/cmd/govulncheck@v1.3.0 ./...

- name: Go Tidy
run: go mod tidy && git diff --exit-code

- name: Go Mod Verify
run: go mod verify

- name: Build
run: go build -o /dev/null ./...

- name: Test
run: go test -v -count=1 -race -shuffle=on -coverprofile=coverage.txt ./...

- name: Coverage summary
run: go tool cover -func=coverage.txt >> "$GITHUB_STEP_SUMMARY"
79 changes: 79 additions & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Go fuzz tests

on:
schedule:
- cron: "0 3 * * 0" # Every Sunday at 03:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
discover:
name: Discover fuzz tests
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Find all fuzz tests
id: set-matrix
run: |
matrix=$(
{ grep -rl "^func Fuzz" transpiler --include="*_test.go" || true; } | sort | while read -r file; do
pkg_dir=$(dirname "$file")
go_pkg="./${pkg_dir#transpiler}"
grep "^func Fuzz" "$file" | sed 's/func \(Fuzz[^(]*\).*/\1/' | while read -r fn; do
printf '{"function":"%s","go_package":"%s","corpus_path":"%s/testdata/fuzz"}\n' \
"$fn" "$go_pkg" "$pkg_dir"
done
done | jq -sc '.'
)
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"

fuzz:
name: ${{ matrix.function }}
needs: discover
if: needs.discover.outputs.matrix != '[]'
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.discover.outputs.matrix) }}
defaults:
run:
working-directory: transpiler
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: transpiler/go.mod
cache: false
- name: Run ${{ matrix.function }}
env:
GO_PKG: ${{ matrix.go_package }}
FUZZ_FN: ${{ matrix.function }}
run: go test "$GO_PKG" "-fuzz=$FUZZ_FN" -fuzztime=5m
- name: Upload fuzz failure seed corpus
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: fuzz-corpus-${{ matrix.function }}
path: ${{ matrix.corpus_path }}/${{ matrix.function }}
- name: Output troubleshooting message
if: failure()
env:
FUZZ_FN: ${{ matrix.function }}
RUN_ID: ${{ github.run_id }}
SHA: ${{ github.sha }}
shell: bash
run: |
echo -e "Fuzz test $FUZZ_FN failed on commit $SHA. To troubleshoot locally, use the GitHub CLI to download the seed corpus with\n\ngh run download $RUN_ID -n fuzz-corpus-$FUZZ_FN\n"
23 changes: 23 additions & 0 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Semgrep

on:
pull_request:
branches: [main]
schedule:
- cron: "0 4 * * 0" # Every Sunday at 04:00 UTC
workflow_dispatch:

permissions:
contents: read

jobs:
semgrep:
name: Semgrep scan
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Run Semgrep
run: pipx run semgrep scan --config=p/golang --config=p/secrets --error
44 changes: 44 additions & 0 deletions .github/workflows/workflow-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Workflow Lint

on:
pull_request:
branches: [main]
paths:
- ".github/workflows/**"
push:
branches: [main]
paths:
- ".github/workflows/**"

permissions:
contents: read

jobs:
zizmor:
name: zizmor
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false

- name: Run zizmor
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
with:
advanced-security: false
inputs: .github/workflows/

actionlint:
name: actionlint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,26 @@ also for AI augmented workflows, where agents can have a source for development.

### Core

- `issue init` - creates a new `.issues` directory in the current directory.
- `issue list` - lists all issues in the current directory.
- `issue create` - creates a new issue in the current directory.
- `issue sync` - syncs all issues in the current directory using the GitHub CLI.
- `issue help`` - shows help for the `issue` command.
- `issues init` - creates a new `.issues` directory in the current directory.
Comment thread
jamesjohnsdev marked this conversation as resolved.
- `issues list` - lists all issues in the current directory.
- `issues create <title>` - creates a new issue in the current directory.
- `issues create -e` - opens a blank issue in the editor without requiring a title upfront (discarded if saved with no title).
- `issues view <number>` - opens an issue by number in the default editor.
- `issues close <number>` - marks an issue as closed.
- `issues sync` - syncs all issues in the current directory using the GitHub CLI.
- `issues help` - shows help for the `issues` command.

### Agentic

These are planned commnads. The idea is that you will define a preferred agent in a config file.

- `issue agent` - sends the current issue to the agent.
- `issue agent list` - sends the list of issues to the agent.
- `issues agent` - sends the current issue to the agent.
- `issues agent list` - sends the list of issues to the agent.

There will be a agent skill created as as well down the line.

## How it works

The `.issue` directory is stored in the project root. It contains a `config.yaml` file. It contains an `issues` directory, which contains current local versions of the issues.
The `.issues` directory is stored in the project root. It contains a `config.yaml` file. It contains an `issues` directory, which contains current local versions of the issues.

There is a `.remote_issues` directory, which contains the remote versions of the issues. During synchronisation, the local versions are updated to match the remote versions.
49 changes: 49 additions & 0 deletions cmd/close.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cmd

import (
"fmt"
"os"
"path/filepath"

"github.com/fatih/color"
"github.com/jamesjohnsdev/issues/internal/issue"
"github.com/spf13/cobra"
)

var closeCmd = &cobra.Command{
Use: "close <number>",
Short: "Mark an issue as closed",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
root, err := issuesRoot()
if err != nil {
return err
}

iss, err := findLocalByID(root, args[0])
if err != nil {
return err
}

if iss.State == "closed" {
fmt.Printf("Issue %s is already closed.\n", args[0])
return nil
}

iss.State = "closed"

newPath := filepath.Join(closedDir(root), filepath.Base(iss.Path))
if err := os.MkdirAll(closedDir(root), 0755); err != nil {
return err
}
if err := issue.Write(newPath, iss); err != nil {
return err
}
if err := os.Remove(iss.Path); err != nil {
return err
}

fmt.Printf("%s %s: %s\n", color.GreenString("Closed"), args[0], iss.Title)
return nil
},
}
Loading