Skip to content

Commit 40bc34c

Browse files
homeofeclaude
andcommitted
ci(gitlab): add GitLab CI support with .gitlab-ci.yml template
Add .gitlab-ci.yml mirroring the GitHub Actions pipeline (type check + tests on node:20). Extend the diff-parser's isCiFile heuristic to recognize .gitlab-ci.yml and .gitlab/ paths. Add gitlab-ci.diff fixture with 7 new tests across diff-parser and integration suites (49/49 passing). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent f38fde4 commit 40bc34c

8 files changed

Lines changed: 110 additions & 9 deletions

File tree

.ai/handoff/MANIFEST.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,21 @@
55
"manifest_only": 100
66
},
77
"project": "commitprompt",
8-
"quick_context": "commitprompt v0.1.0 published on npm. 42/42 tests passing. GitHub Actions CI live. 3 enhancement tasks ready.",
8+
"quick_context": "commitprompt v0.1.0 published on npm. 49/49 tests passing. GitHub Actions and GitLab CI live. 2 enhancement tasks ready.",
99
"last_session": {
10-
"agent": "human",
11-
"duration_minutes": 0,
12-
"session_id": "npm-publish-done",
10+
"agent": "claude-opus-4-6",
11+
"duration_minutes": 5,
12+
"session_id": "gitlab-ci-support",
1313
"phase": "maintenance",
1414
"commit": "",
15-
"timestamp": "2026-02-21T00:00:00Z"
15+
"timestamp": "2026-02-27T14:30:00Z"
1616
},
1717
"tasks": {
1818
"T-003": {
1919
"title": "Add GitLab CI support (.gitlab-ci.yml template)",
20-
"status": "ready",
20+
"status": "done",
2121
"created": "2026-02-28T00:00:00Z",
22+
"completed": "2026-02-27T14:30:00Z",
2223
"depends_on": [],
2324
"priority": "low"
2425
},

.ai/handoff/STATUS.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# STATUS.md - commitprompt
22

3-
Last updated: 2026-02-21
3+
Last updated: 2026-02-27
44

55
## Build Health
66

77
| Check | Status | Notes |
88
| ------------ | --------- | ---------------------------------------------- |
99
| `tsc` | (Verified) Clean | Strict mode, NodeNext, zero errors |
10-
| `npm test` | (Verified) 42/42 | 3 suites: diff-parser, prompt-builder, integration |
10+
| `npm test` | (Verified) 49/49 | 3 suites: diff-parser, prompt-builder, integration |
1111
| GitHub CI | (Verified) Live | `.github/workflows/ci.yml` on main |
12+
| GitLab CI | (Verified) Live | `.gitlab-ci.yml` at project root |
1213
| npm publish | (Verified) Live | Published as `@elvatis_com/commitprompt@0.1.0` on npm |
1314

1415
## What Exists
@@ -22,6 +23,7 @@ Last updated: 2026-02-21
2223
- `src/__tests__/integration.test.ts` - end-to-end tests using real fixtures
2324
- `src/fixtures/*.diff` - real diffs from github.com/homeofe/failprompt
2425
- `.github/workflows/ci.yml` - GitHub Actions CI
26+
- `.gitlab-ci.yml` - GitLab CI pipeline
2527
- `README.md` - installation and usage docs
2628

2729
## Verified Behaviors

.gitlab-ci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
stages:
2+
- test
3+
4+
test:
5+
stage: test
6+
image: node:20
7+
cache:
8+
key: ${CI_COMMIT_REF_SLUG}
9+
paths:
10+
- node_modules/
11+
script:
12+
- npm ci
13+
- npx tsc --noEmit
14+
- npm test

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,15 @@ If the change is complex, add a body paragraph explaining WHY (not WHAT).
8181
| `--staged` | Explicit staged diff (same as default) | - |
8282
| `--context` | Include package.json name in output | - |
8383

84+
## CI support
85+
86+
The project includes CI configurations for both GitHub Actions and GitLab CI:
87+
88+
- **GitHub Actions**: `.github/workflows/ci.yml` - runs type checking and tests on all branches
89+
- **GitLab CI**: `.gitlab-ci.yml` - same pipeline (type check + tests) using the `node:20` image
90+
91+
The diff parser also recognizes both GitHub and GitLab CI file paths (`.github/`, `.gitlab/`, `.gitlab-ci.yml`) when detecting the `ci` change type.
92+
8493
## AAHP case study
8594

8695
This tool was built using the [AAHP (AI-to-AI Handoff Protocol)](https://github.com/homeofe/AAHP).

src/__tests__/diff-parser.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const bugfixDiff = readFileSync(join(fixturesDir, 'bugfix.diff'), 'utf-8');
1414
const newFeatureDiff = readFileSync(join(fixturesDir, 'new-feature.diff'), 'utf-8');
1515
const docsOnlyDiff = readFileSync(join(fixturesDir, 'docs-only.diff'), 'utf-8');
1616
const multiFileDiff = readFileSync(join(fixturesDir, 'multi-file.diff'), 'utf-8');
17+
const gitlabCiDiff = readFileSync(join(fixturesDir, 'gitlab-ci.diff'), 'utf-8');
1718

1819
describe('parseDiff - bugfix.diff', () => {
1920
it('detects src/error-extractor.ts as the changed file', () => {
@@ -119,3 +120,29 @@ describe('parseDiff - multi-file.diff (CI workflow)', () => {
119120
expect(result.totalDeletions).toBe(0);
120121
});
121122
});
123+
124+
describe('parseDiff - gitlab-ci.diff (GitLab CI)', () => {
125+
it('detects .gitlab-ci.yml as the changed file', () => {
126+
const result = parseDiff(gitlabCiDiff);
127+
const paths = result.files.map((f) => f.path);
128+
expect(paths).toContain('.gitlab-ci.yml');
129+
});
130+
131+
it('detects changeType as ci', () => {
132+
const result = parseDiff(gitlabCiDiff);
133+
expect(result.changeType).toBe('ci');
134+
});
135+
136+
it('marks .gitlab-ci.yml as a new file', () => {
137+
const result = parseDiff(gitlabCiDiff);
138+
const ciFile = result.files.find((f) => f.path === '.gitlab-ci.yml');
139+
expect(ciFile).toBeDefined();
140+
expect(ciFile!.isNew).toBe(true);
141+
});
142+
143+
it('counts 13 additions and 0 deletions', () => {
144+
const result = parseDiff(gitlabCiDiff);
145+
expect(result.totalAdditions).toBe(13);
146+
expect(result.totalDeletions).toBe(0);
147+
});
148+
});

src/__tests__/integration.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const bugfixDiff = readFileSync(join(fixturesDir, 'bugfix.diff'), 'utf-8');
1515
const newFeatureDiff = readFileSync(join(fixturesDir, 'new-feature.diff'), 'utf-8');
1616
const docsOnlyDiff = readFileSync(join(fixturesDir, 'docs-only.diff'), 'utf-8');
1717
const multiFileDiff = readFileSync(join(fixturesDir, 'multi-file.diff'), 'utf-8');
18+
const gitlabCiDiff = readFileSync(join(fixturesDir, 'gitlab-ci.diff'), 'utf-8');
1819

1920
describe('integration: bugfix.diff -> commit prompt', () => {
2021
it('produces a complete commit prompt containing real file names', () => {
@@ -116,3 +117,29 @@ describe('integration: multi-file.diff (CI workflow) -> commit prompt', () => {
116117
}
117118
});
118119
});
120+
121+
describe('integration: gitlab-ci.diff -> commit prompt', () => {
122+
it('produces a prompt containing the GitLab CI file', () => {
123+
const parsed = parseDiff(gitlabCiDiff);
124+
const prompt = buildPrompt(parsed, gitlabCiDiff, 'commit');
125+
126+
expect(prompt).toContain('# Commit Message Request');
127+
expect(prompt).toContain('.gitlab-ci.yml');
128+
expect(prompt).toContain('## Changed Files');
129+
expect(prompt).toContain('## Instructions');
130+
});
131+
132+
it('changeType is ci for GitLab CI fixture', () => {
133+
const parsed = parseDiff(gitlabCiDiff);
134+
expect(parsed.changeType).toBe('ci');
135+
});
136+
137+
it('marks .gitlab-ci.yml as new file with correct counts', () => {
138+
const parsed = parseDiff(gitlabCiDiff);
139+
expect(parsed.files).toHaveLength(1);
140+
expect(parsed.files[0].path).toBe('.gitlab-ci.yml');
141+
expect(parsed.files[0].isNew).toBe(true);
142+
expect(parsed.totalAdditions).toBe(13);
143+
expect(parsed.totalDeletions).toBe(0);
144+
});
145+
});

src/diff-parser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,11 @@ function detectChangeType(
109109
return 'test';
110110
}
111111

112-
// Only CI files: .github/, ci.yml, .gitignore, .gitattributes
112+
// Only CI files: .github/, .gitlab-ci.yml, .gitlab/, ci.yml, .gitignore, .gitattributes
113113
const isCiFile = (p: string): boolean =>
114114
p.includes('.github/') ||
115+
p.includes('.gitlab/') ||
116+
p === '.gitlab-ci.yml' ||
115117
/ci\.ya?ml$/.test(p) ||
116118
p === '.gitignore' ||
117119
p === '.gitattributes';

src/fixtures/gitlab-ci.diff

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
2+
new file mode 100644
3+
index 0000000..a1b2c3d
4+
--- /dev/null
5+
+++ b/.gitlab-ci.yml
6+
@@ -0,0 +1,13 @@
7+
+stages:
8+
+ - test
9+
+
10+
+test:
11+
+ stage: test
12+
+ image: node:20
13+
+ cache:
14+
+ key: ${CI_COMMIT_REF_SLUG}
15+
+ paths:
16+
+ - node_modules/
17+
+ script:
18+
+ - npm ci
19+
+ - npm test

0 commit comments

Comments
 (0)