Skip to content

Commit 29b8e58

Browse files
authored
docs: align README (drop use-case diagram, add gitlab-init & /gitlab-doctor) + add examples/ (#26)
* fix: correct invalid glab commands; add gitlab-doctor + bump-version tooling Validated against glab 1.95.0; replace non-existent commands the skills relied on: - milestone close/reopen -> milestone edit --state close/activate - issue edit / mr edit -> issue update / mr update - issue link --target-id -> glab api projects/:id/issues/<iid>/links - --related-issue-id -> --linked-issues - issue list --state opened -> issue list (open by default) Centralize the new anti-patterns in shared/glab-command-index.md. Other changes: - rename skill gitlab-setup -> gitlab-init (project label initializer) - add /gitlab-doctor command (glab install + auth health check, with help) - add scripts/bump-version.sh + .version-bump.json (plugin-level version sync, raw+json) - bump versions: plugin 1.3.0->1.4.0; gitlab-plan 1.2.1, track/story/review 1.3.1, init 1.0.1 - prettier pass on markdown; includes carried WIP from develop (personas, CLAUDE.md) * docs: align README — drop use-case diagram, add gitlab-init & /gitlab-doctor - Remove the Mermaid sequence (use-case) diagram and "Workflow overview" section (kept Mermaid-as-feature mentions: skills still generate diagrams in artifacts) - Add gitlab-init skill section (project label initializer, formerly gitlab-setup) - Add /gitlab-doctor command section (glab install + auth health check) - Fix stale glab commands in prose: milestone close/reopen -> edit --state; issue link --target-id -> glab api .../links - Add gitlab-init as step 0 in the full sprint cycle example * docs: add examples/ with generated artifacts (issues, MRs, milestone) - examples/issues/ — 4 gitlab-track issues: ERR-001 (bug), CONC-004 (tech-debt, Mermaid), SEC-003 (security bug, DREAD, Mermaid), PERF-001 (tech-debt) - examples/merge-requests/ — 2 gitlab-review MRs: feat (apiclient pool/retry), fix (error-handling OTel v2) - examples/milestones/ — 1 gitlab-plan milestone from assets/milestone.md template - examples/README.md — index All examples in English, fully genericized (gitlab.example.com/acme/platform-scraper), no internal references; sourced from real artifacts with encoding cleaned up.
1 parent d58dd22 commit 29b8e58

9 files changed

Lines changed: 845 additions & 73 deletions

README.md

Lines changed: 40 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -28,75 +28,22 @@ does it publish to GitLab.
2828
Artifacts are language-agnostic: section headings and prose follow your active language at
2929
runtime. No language is hardcoded.
3030

31-
## Workflow overview
32-
33-
The five skills cover the full GitLab development lifecycle from sprint planning to merge:
34-
35-
```mermaid
36-
sequenceDiagram
37-
actor Dev as Developer
38-
participant A as AI Agent
39-
participant GL as GitLab
40-
41-
Dev->>A: "Plan sprint 3: auth migration"
42-
A->>GL: glab milestone create
43-
GL-->>A: milestone/3
44-
A-->>Dev: ✓ Milestone #3 created
45-
46-
Dev->>A: "Create a story for the auth migration"
47-
A->>GL: glab label list + milestone list
48-
A-->>Dev: Draft story — approve?
49-
Dev->>A: yes
50-
A->>GL: glab issue create (kind::story)
51-
GL-->>A: issue #10
52-
A-->>Dev: ✓ Story #10 created
53-
54-
Dev->>A: "Add issues #11 #12 as children of #10"
55-
A->>GL: glab issue view #11 / #12
56-
A->>GL: glab issue link #11 --target-id #10
57-
A->>GL: glab issue link #12 --target-id #10
58-
A-->>Dev: Updated children table — approve?
59-
Dev->>A: yes
60-
A->>GL: glab issue update #10
61-
A-->>Dev: ✓ Children linked
62-
63-
Dev->>A: "Start working on issue #11"
64-
A->>GL: glab issue edit #11 (workflow::in dev)
65-
A-->>Dev: ✓ Branch fix/11-oauth-handler created
66-
67-
Note over Dev,GL: ... development ...
68-
69-
Dev->>A: "Commit staged changes"
70-
A-->>Dev: fix(#11): handle OAuth token expiry — approve?
71-
Dev->>A: yes
72-
A->>A: git commit
73-
A-->>Dev: ✓ Committed abc1234
74-
75-
Dev->>A: "Create MR for this branch and close #11"
76-
A->>GL: glab label list + diff analysis
77-
A-->>Dev: Draft MR — approve?
78-
Dev->>A: yes
79-
A->>GL: glab mr create
80-
GL-->>A: MR !5
81-
A-->>Dev: ✓ MR !5 created
82-
83-
Dev->>A: "Link MR !5 to story #10"
84-
A->>GL: glab mr view !5 + commits
85-
A-->>Dev: Updated parent issue — approve?
86-
Dev->>A: yes
87-
A->>GL: glab issue update #10
88-
A-->>Dev: ✓ Story #10 updated with MR reference
89-
90-
Dev->>A: "Sync story #10 children status"
91-
A->>GL: glab issue view #11 + #12
92-
A-->>Dev: Before/after table diff — approve?
93-
Dev->>A: yes
94-
A->>GL: glab issue update #10
95-
A-->>Dev: ✓ Children table synced
96-
```
97-
9831
## Skills
9932

33+
### `gitlab-init` — Project label initializer
34+
35+
**Trigger phrases:** "Setup GitLab", "Initialize the project labels", "Configure labels",
36+
"Init GitLab project"
37+
38+
**What it produces:**
39+
40+
- The labels the workflow relies on (`workflow::*`, `type::*`, `kind::*`), created in the current project
41+
- Idempotent — labels already present are skipped, so it is safe to re-run any number of times
42+
43+
**Boundary:** one-time project bootstrap. Not for issue creation (→ `gitlab-track`) or milestones (→ `gitlab-plan`).
44+
45+
---
46+
10047
### `gitlab-plan` — Milestone author
10148

10249
**Trigger phrases:** "Create a milestone", "Plan sprint 5", "Start release v2.1",
@@ -110,11 +57,11 @@ sequenceDiagram
11057

11158
**Modes:**
11259

113-
| Mode | Command | When to use |
114-
| -------------- | ------------------------------- | ------------------------------------------- |
115-
| Create | `glab milestone create` | New sprint or release |
116-
| Update | `glab milestone edit` | Extend deadline, rename, update description |
117-
| Close / Reopen | `glab milestone close / reopen` | End of sprint; re-open if work resumes |
60+
| Mode | Command | When to use |
61+
| -------------- | ---------------------------------------------- | ------------------------------------------- |
62+
| Create | `glab milestone create` | New sprint or release |
63+
| Update | `glab milestone edit` | Extend deadline, rename, update description |
64+
| Close / Reopen | `glab milestone edit --state close / activate` | End of sprint; re-open if work resumes |
11865

11966
**Context extracted silently:** recent git log, active branches, existing milestones, open issues.
12067

@@ -242,7 +189,8 @@ markdown children table tracking all child issues:
242189
| [#12](…) | Add refresh token rotation | `type::feature` | `workflow::ready` | — |
243190
```
244191

245-
Child issues are linked to the parent via `glab issue link --link-type relates_to`.
192+
Child issues are linked to the parent via the Issue Links REST API
193+
(`glab api --method POST "projects/:id/issues/<iid>/links"`, `link_type=relates_to`).
246194

247195
**Modes:**
248196

@@ -268,6 +216,24 @@ No GitLab Premium required. Hierarchy state is persisted entirely in the parent
268216

269217
---
270218

219+
## Commands
220+
221+
### `/gitlab-doctor` — Environment health check
222+
223+
A slash command (not a skill) that verifies your setup before running the workflow skills:
224+
225+
- Confirms the `glab` CLI is installed
226+
- Confirms you are authenticated (`glab auth status`)
227+
- Prints install/login guidance and exits non-zero when something is missing
228+
229+
```
230+
/gitlab-doctor # check gitlab.com
231+
/gitlab-doctor <hostname> # check a self-managed instance
232+
/gitlab-doctor help # usage
233+
```
234+
235+
---
236+
271237
## Installation
272238

273239
### Claude Code
@@ -332,6 +298,7 @@ mkdir -p .codex/skills && cp -r /tmp/gitlab-workflow/skills/. .codex/skills/
332298
### Full sprint cycle (sequence)
333299

334300
```
301+
0. "Setup the project labels" → gitlab-init
335302
1. "Create milestone Sprint 3" → gitlab-plan
336303
2. "Create a story for OAuth migration" → gitlab-story (Create)
337304
3. "Add issues #11 #12 as children of story #10" → gitlab-story (Add-Child)

examples/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Examples
2+
3+
Real-world artifacts produced by the `gitlab-workflow` skills, **genericized**: every internal
4+
host/path has been replaced with `gitlab.example.com/acme/platform-scraper`. They illustrate the
5+
structure each skill generates — YAML frontmatter, sections, fenced code snippets with
6+
`path/file.ext line N` citations, Mermaid diagrams, and `Closes #N` / `Related to #N` footers.
7+
8+
## Milestones — produced by `gitlab-plan`
9+
10+
| File | Highlights |
11+
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
12+
| [v1.4.0 — platform-scraper hardening](milestones/v1.4.0-platform-scraper-hardening.md) | objective, deliverables, linked epics, completion criteria (from `assets/milestone.md`) |
13+
14+
## Issues — produced by `gitlab-track`
15+
16+
| File | Type | Highlights |
17+
| -------------------------------------------------------------------------------------- | ---------------------- | ------------------------------- |
18+
| [ERR-001 — abort on tracer init failure](issues/err-001-abort-tracer-init-failure.md) | `type::bug` | repro steps, snippet, impact |
19+
| [CONC-004 — idempotent Shutdown with sync.Once](issues/conc-004-shutdown-sync-once.md) | `type::technical-debt` | Mermaid sequence, tasks |
20+
| [SEC-003 — enforce TLS 1.2 on the HTTP client](issues/sec-003-tls-minversion-http.md) | `type::bug` | security, DREAD score, Mermaid |
21+
| [PERF-001 — reuse a single http.Client](issues/perf-001-single-http-client.md) | `type::technical-debt` | before/after code, pprof impact |
22+
23+
## Merge requests — produced by `gitlab-review`
24+
25+
| File | Type | Highlights |
26+
| ------------------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------- |
27+
| [feat: apiclient with TCP pool & retry](merge-requests/feat-apiclient-pool-retry.md) | `feat` | multi-issue close, snippets, reviewer notes |
28+
| [fix: error-handling consistency (OTel v2, fatal startup)](merge-requests/error-handling-otel-v2-fatal-startup.md) | `fix` | closes 3 issues, ADR refs, reviewer notes |
29+
30+
> These are illustrative outputs. The Mermaid diagrams are part of what the skills generate when
31+
> the policy calls for them; section headings follow the user's active language at runtime (here,
32+
> English).
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
---
2+
kind: issue
3+
type: technical-debt
4+
title: "[CONC-004] Ensure Shutdown runs at most once with sync.Once"
5+
labels: "type::technical-debt,concurrency,workflow::ready,component: platform-scraper,Priority Low"
6+
milestone: "v1.4.0"
7+
status: published
8+
gitlab_url: https://gitlab.example.com/acme/platform-scraper/-/issues/42
9+
published_at: 2026-06-03
10+
created_at: 2026-06-03
11+
---
12+
13+
## Description
14+
15+
### 1. `Shutdown` called from two goroutines without protection
16+
17+
`scraperManager.Shutdown` can be invoked concurrently from both the signal goroutine (line 76)
18+
and the execute goroutine (line 93):
19+
20+
```go
21+
// main.go line 76-78 — signal goroutine
22+
if err := scraperManager.Shutdown(ctx); err != nil {
23+
log.Error().Err(err).Msg("Main: scraper shutdown failed")
24+
}
25+
26+
// main.go line 93-95 — execute goroutine
27+
if err := scraperManager.Shutdown(ctx); err != nil {
28+
log.Error().Err(err).Msg("Main: scraper shutdown failed")
29+
}
30+
```
31+
32+
The current `Shutdown` implementation is a no-op:
33+
34+
```go
35+
// app/scraper/scraperController.go line 104-107
36+
func (sc *Manager) Shutdown(ctx context.Context) error {
37+
log.Debug().Msgf("ScraperManager::Shutdown shutdown scraper controller")
38+
return nil
39+
}
40+
```
41+
42+
Any future change to `Shutdown` that reads or mutates internal `Manager` state will introduce a
43+
data race detectable by `go test -race`.
44+
45+
### 2. Concurrent Shutdown calls
46+
47+
```mermaid
48+
sequenceDiagram
49+
participant GS as signal-goroutine
50+
participant GE as execute-goroutine
51+
participant SM as Manager.Shutdown
52+
53+
GS->>SM: Shutdown(ctx) — from signal
54+
GE->>SM: Shutdown(ctx) — from execute
55+
Note over SM: Two concurrent calls without sync
56+
Note over SM: Data race on any future state
57+
```
58+
59+
---
60+
61+
## Steps to reproduce
62+
63+
1. Add any mutable field touched by `Manager.Shutdown`.
64+
2. Run `go test -race ./...` with a test that simulates SIGTERM during Execute.
65+
3. The race detector reports the data race.
66+
67+
---
68+
69+
## Expected behavior
70+
71+
Concurrent calls to `Shutdown` are safe: the shutdown logic runs at most once thanks to
72+
`sync.Once`.
73+
74+
---
75+
76+
## Actual behavior
77+
78+
Two concurrent `Shutdown` calls access shared `Manager` state without synchronization.
79+
80+
---
81+
82+
## Impact
83+
84+
Any future evolution of `Shutdown` that writes to `Manager` fields introduces a data race that is
85+
not immediately visible. The `Shutdown` contract does not guarantee concurrent idempotency.
86+
87+
---
88+
89+
## Related issues
90+
91+
- Epic: [#39 — CONC Concurrency Safety](https://gitlab.example.com/acme/platform-scraper/-/issues/39)
92+
- Related to CONC-001, CONC-002
93+
94+
---
95+
96+
## Affected files
97+
98+
- `main.go` — lines 76–78, 93–95
99+
- `app/scraper/scraperController.go` — lines 104–107
100+
101+
---
102+
103+
## Tasks
104+
105+
- [ ] Add a `shutdownOnce sync.Once` field to `Manager`
106+
- [ ] Wrap the `Shutdown` logic with `sc.shutdownOnce.Do(func() { ... })`
107+
- [ ] `go test -race ./...` with no shutdown-related data-race report
108+
- [ ] `golangci-lint run` with no additional errors
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
kind: issue
3+
type: bug
4+
title: "[ERR-001] Abort startup when tracer initialization fails"
5+
labels: "type::bug,error-handling,workflow::ready,component: platform-scraper,Priority High"
6+
milestone: "v1.4.0"
7+
status: published
8+
gitlab_url: https://gitlab.example.com/acme/platform-scraper/-/issues/77
9+
published_at: 2026-06-03
10+
created_at: 2026-06-03
11+
---
12+
13+
## Description
14+
15+
### `initTracer` error ignored — execution continues with a broken tracer
16+
17+
`main.go` logs the `initTracer` error but keeps running:
18+
19+
```go
20+
// main.go line 50-53
21+
tracerShutdown, err := initTracer(ctx)
22+
if err != nil {
23+
log.Error().Err(err).Msg("Main: Error in initializing tracer")
24+
// missing os.Exit(1) — execution continues
25+
}
26+
```
27+
28+
The code below checks `tracerShutdown != nil` before calling it (line 71), but `tracerShutdown`
29+
is nil when `initTracer` fails: the whole scrape session emits empty/disconnected spans to the
30+
OTel collector for the entire run.
31+
32+
---
33+
34+
## Steps to reproduce
35+
36+
1. Configure an unreachable or invalid OTel endpoint.
37+
2. Start `platform-scraper`.
38+
3. Observe: the process starts, scrapes data, and publishes it with no traces.
39+
40+
---
41+
42+
## Expected behavior
43+
44+
`initTracer` fails → log the error wrapped with context → `os.Exit(1)`.
45+
46+
---
47+
48+
## Actual behavior
49+
50+
The process starts normally with tracing broken, producing an entire untraced scrape cycle with
51+
no operational signal.
52+
53+
---
54+
55+
## Impact
56+
57+
The operator gets no signal that tracing is broken: the OTel dashboard shows trace gaps with no
58+
alert. The problem can go unnoticed for several cycles.
59+
60+
---
61+
62+
## Related issues
63+
64+
- Epic: [#66 — ERR Error Handling Consistency](https://gitlab.example.com/acme/platform-scraper/-/issues/66)
65+
66+
---
67+
68+
## Affected files
69+
70+
- `main.go` — lines 50–53
71+
72+
---
73+
74+
## Tasks
75+
76+
- [ ] Add `os.Exit(1)` after the error log in the `initTracer` failure branch
77+
- [ ] Wrap the error with `fmt.Errorf("initializing tracer: %w", err)` before logging
78+
- [ ] Remove the nil-check on `tracerShutdown` (line 71): after the fix, `tracerShutdown` is always valid if execution reaches that point
79+
- [ ] `golangci-lint run` with no additional errors

0 commit comments

Comments
 (0)