agent-flutter 0.1.22 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/cli.js +24 -1
- package/templates/shared/TEMPLATES.md +19 -0
- package/templates/shared/github/pull_request_template.md +26 -0
- package/templates/shared/github/workflows/pr-template-gate.yml +102 -0
- package/templates/shared/rules/ci-cd-pr.md +47 -0
package/README.md
CHANGED
|
@@ -76,4 +76,4 @@ npm run release:major
|
|
|
76
76
|
- Cursor: `.cursor/skills/`, `.cursor/rules/shared/`, `.cursor/scripts/`, `.cursor/rules/agent-flutter.mdc`
|
|
77
77
|
- Windsurf: `.windsurf/skills/`, `.windsurf/rules/shared/`, `.windsurf/scripts/`, `.windsurf/rules/agent-flutter.md`
|
|
78
78
|
- Cline: `.clinerules/skills/`, `.clinerules/rules/`, `.clinerules/scripts/`, `.clinerules/agent-flutter.md`
|
|
79
|
-
- GitHub: `.github/skills/`, `.github/rules/`, `.github/scripts/`, `.github/copilot-instructions.md`
|
|
79
|
+
- GitHub: `.github/skills/`, `.github/rules/`, `.github/scripts/`, `.github/copilot-instructions.md`, `.github/pull_request_template.md`, `.github/workflows/pr-template-gate.yml`
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -399,6 +399,25 @@ async function applyPack({
|
|
|
399
399
|
});
|
|
400
400
|
console.log(`${verb} GitHub rules: ${githubRulesPath}`);
|
|
401
401
|
}
|
|
402
|
+
|
|
403
|
+
const githubPrTemplateSource = path.join(templateRoot, 'github', 'pull_request_template.md');
|
|
404
|
+
if (await exists(githubPrTemplateSource)) {
|
|
405
|
+
await syncTemplateFile({
|
|
406
|
+
sourcePath: githubPrTemplateSource,
|
|
407
|
+
destinationPath: path.join(projectRoot, '.github', 'pull_request_template.md'),
|
|
408
|
+
label: 'GitHub PR template',
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const githubPrGateSource = path.join(templateRoot, 'github', 'workflows', 'pr-template-gate.yml');
|
|
413
|
+
if (await exists(githubPrGateSource)) {
|
|
414
|
+
await syncTemplateFile({
|
|
415
|
+
sourcePath: githubPrGateSource,
|
|
416
|
+
destinationPath: path.join(projectRoot, '.github', 'workflows', 'pr-template-gate.yml'),
|
|
417
|
+
label: 'GitHub PR gate workflow',
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
402
421
|
const githubPath = path.join(projectRoot, '.github', 'copilot-instructions.md');
|
|
403
422
|
const written = await writeTextFile(
|
|
404
423
|
githubPath,
|
|
@@ -697,7 +716,8 @@ Use local instructions from \`.cursor\`.
|
|
|
697
716
|
Priority:
|
|
698
717
|
1. \`.cursor/rules/shared/ui.md\`
|
|
699
718
|
2. \`.cursor/rules/shared/integration-api.md\`
|
|
700
|
-
3. \`.cursor/rules/shared/
|
|
719
|
+
3. \`.cursor/rules/shared/ci-cd-pr.md\`
|
|
720
|
+
4. \`.cursor/rules/shared/unit-test.md\` and \`.cursor/rules/shared/widget-test.md\`
|
|
701
721
|
|
|
702
722
|
When a task matches a skill, load the corresponding \`SKILL.md\` under:
|
|
703
723
|
\`.cursor/skills/<skill>/SKILL.md\`
|
|
@@ -717,6 +737,7 @@ Required order:
|
|
|
717
737
|
2. If task matches a skill, load \`.windsurf/skills/<skill>/SKILL.md\`.
|
|
718
738
|
3. For new project scaffolding, run \`bash .windsurf/scripts/bootstrap_flutter_template.sh\`.
|
|
719
739
|
4. Keep spec documentation synchronized after UI/API changes.
|
|
740
|
+
5. For completed UI/API features, follow \`.windsurf/rules/shared/ci-cd-pr.md\` before handoff.
|
|
720
741
|
`;
|
|
721
742
|
}
|
|
722
743
|
|
|
@@ -731,6 +752,7 @@ Execution checklist:
|
|
|
731
752
|
3. For new project scaffolding, run \`bash .clinerules/scripts/bootstrap_flutter_template.sh\`.
|
|
732
753
|
4. Preserve Flutter architecture conventions and localization requirements.
|
|
733
754
|
5. Update docs/specs after behavior changes.
|
|
755
|
+
6. For completed UI/API features, follow \`.clinerules/rules/ci-cd-pr.md\` before handoff.
|
|
734
756
|
`;
|
|
735
757
|
}
|
|
736
758
|
|
|
@@ -745,6 +767,7 @@ Follow this order when generating code:
|
|
|
745
767
|
3. For new project scaffolding, run \`bash .github/scripts/bootstrap_flutter_template.sh\`.
|
|
746
768
|
4. Keep architecture, localization, and UI conventions aligned with local instructions.
|
|
747
769
|
5. Update specs/docs when UI/API behavior changes.
|
|
770
|
+
6. For completed UI/API features, follow \`.github/rules/ci-cd-pr.md\` before final handoff.
|
|
748
771
|
`;
|
|
749
772
|
}
|
|
750
773
|
|
|
@@ -52,3 +52,22 @@ Refactor this page: [Path to file]
|
|
|
52
52
|
- Replace raw widgets with `App*` widgets.
|
|
53
53
|
- Fix hardcoded strings/colors.
|
|
54
54
|
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## **4. Finalize Feature (Commit + Push + PR)**
|
|
59
|
+
|
|
60
|
+
Use this after completing UI/API work to trigger CI/CD rule and PR creation:
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
Finalize this feature:
|
|
64
|
+
- Branch name: [e.g. feat/login-session-timeout]
|
|
65
|
+
- Commit message: [e.g. feat(auth): handle session timeout]
|
|
66
|
+
- Base branch: [e.g. dev]
|
|
67
|
+
- PR title: [e.g. feat(auth): handle session timeout]
|
|
68
|
+
- Feature summary: [...]
|
|
69
|
+
- UI summary: [...]
|
|
70
|
+
- Reviewer notes: [...]
|
|
71
|
+
- Screenshot evidence: [No UI OR before/after]
|
|
72
|
+
- Paired with: [Solo OR name]
|
|
73
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
### 🗃 Issue Or Explanation for this PR. (What is it supposed to do and Why is needed)
|
|
2
|
+
|
|
3
|
+
- Feature:
|
|
4
|
+
- UI:
|
|
5
|
+
|
|
6
|
+
### ✅ Checklist
|
|
7
|
+
|
|
8
|
+
- [ ] Issue Or Task detail are up to date for people to QA
|
|
9
|
+
- [ ] I have functionally tested all my changes
|
|
10
|
+
- [ ] I handled the code format
|
|
11
|
+
- [ ] I have Tested on Android (only App)
|
|
12
|
+
- [ ] I have Tested on iOS (only App)
|
|
13
|
+
|
|
14
|
+
### 🕵️♂️ Notes for Code Reviewer
|
|
15
|
+
|
|
16
|
+
Example: Change the Subscription Billing Flow with using SetupIntent to collect user billing information first.
|
|
17
|
+
|
|
18
|
+
### 🙈 Screenshots
|
|
19
|
+
|
|
20
|
+
No UI
|
|
21
|
+
or take screenshot before change and after change
|
|
22
|
+
Or take a screenshot of the design if the task is new
|
|
23
|
+
|
|
24
|
+
### 👯♀️ Paired with
|
|
25
|
+
|
|
26
|
+
Solo
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: PR Template Gate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types:
|
|
6
|
+
- opened
|
|
7
|
+
- edited
|
|
8
|
+
- reopened
|
|
9
|
+
- synchronize
|
|
10
|
+
- ready_for_review
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
validate-pr-template:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Validate PR body sections and checklist
|
|
17
|
+
uses: actions/github-script@v7
|
|
18
|
+
with:
|
|
19
|
+
script: |
|
|
20
|
+
const body = (context.payload.pull_request.body || "").trim();
|
|
21
|
+
const errors = [];
|
|
22
|
+
|
|
23
|
+
function escapeRegExp(value) {
|
|
24
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function requirePattern(regex, message) {
|
|
28
|
+
if (!regex.test(body)) {
|
|
29
|
+
errors.push(message);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function sectionBetween(startHeading, endHeading) {
|
|
34
|
+
const start = body.indexOf(startHeading);
|
|
35
|
+
if (start === -1) return "";
|
|
36
|
+
const afterStart = start + startHeading.length;
|
|
37
|
+
const end = endHeading ? body.indexOf(endHeading, afterStart) : body.length;
|
|
38
|
+
const raw = end === -1 ? body.slice(afterStart) : body.slice(afterStart, end);
|
|
39
|
+
return raw.trim();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const requiredHeadings = [
|
|
43
|
+
"### 🗃 Issue Or Explanation for this PR. (What is it supposed to do and Why is needed)",
|
|
44
|
+
"### ✅ Checklist",
|
|
45
|
+
"### 🕵️♂️ Notes for Code Reviewer",
|
|
46
|
+
"### 🙈 Screenshots",
|
|
47
|
+
"### 👯♀️ Paired with",
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
for (const heading of requiredHeadings) {
|
|
51
|
+
if (!body.includes(heading)) {
|
|
52
|
+
errors.push(`Missing section: ${heading}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
requirePattern(/^- Feature:\s*\S.+/m, "Missing or empty `- Feature:` line.");
|
|
57
|
+
requirePattern(/^- UI:\s*\S.+/m, "Missing or empty `- UI:` line.");
|
|
58
|
+
|
|
59
|
+
const checklistItems = [
|
|
60
|
+
"Issue Or Task detail are up to date for people to QA",
|
|
61
|
+
"I have functionally tested all my changes",
|
|
62
|
+
"I handled the code format",
|
|
63
|
+
"I have Tested on Android (only App)",
|
|
64
|
+
"I have Tested on iOS (only App)",
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
for (const item of checklistItems) {
|
|
68
|
+
const regex = new RegExp(`^- \\[(x|X)\\] ${escapeRegExp(item)}\\s*$`, "m");
|
|
69
|
+
if (!regex.test(body)) {
|
|
70
|
+
errors.push(`Checklist item must be checked [x]: ${item}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const notesSection = sectionBetween(
|
|
75
|
+
"### 🕵️♂️ Notes for Code Reviewer",
|
|
76
|
+
"### 🙈 Screenshots",
|
|
77
|
+
);
|
|
78
|
+
if (!notesSection || /^Example:/i.test(notesSection)) {
|
|
79
|
+
errors.push("Notes for Code Reviewer must contain actual reviewer notes, not only the example.");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const screenshotSection = sectionBetween(
|
|
83
|
+
"### 🙈 Screenshots",
|
|
84
|
+
"### 👯♀️ Paired with",
|
|
85
|
+
);
|
|
86
|
+
const hasNoUi = /No UI/i.test(screenshotSection);
|
|
87
|
+
const hasImage = /!\[[^\]]*\]\([^)]+\)/.test(screenshotSection);
|
|
88
|
+
const hasBeforeAfter = /before/i.test(screenshotSection) && /after/i.test(screenshotSection);
|
|
89
|
+
if (!screenshotSection || (!hasNoUi && !hasImage && !hasBeforeAfter)) {
|
|
90
|
+
errors.push("Screenshots section must include `No UI`, markdown image(s), or before/after evidence.");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const pairedSection = sectionBetween("### 👯♀️ Paired with", null);
|
|
94
|
+
if (!pairedSection) {
|
|
95
|
+
errors.push("Paired with section cannot be empty (e.g. `Solo`).");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (errors.length > 0) {
|
|
99
|
+
core.setFailed(["PR template validation failed:", ...errors.map(e => `- ${e}`)].join("\n"));
|
|
100
|
+
} else {
|
|
101
|
+
core.info("PR template validation passed.");
|
|
102
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
---
|
|
4
|
+
# CI/CD Rule - Commit, Push, Pull Request Gate
|
|
5
|
+
|
|
6
|
+
## 1. Trigger
|
|
7
|
+
Apply this rule after completing any feature that follows:
|
|
8
|
+
- `ui.md`
|
|
9
|
+
- `integration-api.md`
|
|
10
|
+
|
|
11
|
+
This is the required "done" flow before feature handoff.
|
|
12
|
+
|
|
13
|
+
## 2. Required Flow
|
|
14
|
+
1. Verify quality gates:
|
|
15
|
+
- `fvm flutter analyze`
|
|
16
|
+
- Run related tests for the changed scope (unit/widget/integration when available).
|
|
17
|
+
2. Ensure spec/docs are updated if behavior changed.
|
|
18
|
+
3. Commit with clear scope and summary.
|
|
19
|
+
4. Push branch to remote.
|
|
20
|
+
5. Create PR with mandatory template sections.
|
|
21
|
+
|
|
22
|
+
If any step is skipped, feature is not considered complete.
|
|
23
|
+
|
|
24
|
+
## 3. Git Commands (Reference)
|
|
25
|
+
```bash
|
|
26
|
+
git checkout -b feat/<feature-name>
|
|
27
|
+
git add -A
|
|
28
|
+
git commit -m "feat(<scope>): <short summary>"
|
|
29
|
+
git push -u origin HEAD
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 4. PR Body Policy (Mandatory)
|
|
33
|
+
PR must follow `.github/pull_request_template.md` and include all sections:
|
|
34
|
+
- Issue/Explanation (with `Feature` and `UI` lines).
|
|
35
|
+
- Checklist (all required items checked `[x]`).
|
|
36
|
+
- Notes for reviewer.
|
|
37
|
+
- Screenshots section (`No UI` or actual screenshots/evidence).
|
|
38
|
+
- Paired with.
|
|
39
|
+
|
|
40
|
+
## 5. Merge Gate
|
|
41
|
+
- CI workflow `PR Template Gate` validates PR body.
|
|
42
|
+
- If required section/checklist is missing, CI fails.
|
|
43
|
+
- Branch protection must require this check before merge.
|
|
44
|
+
|
|
45
|
+
## 6. Agent Behavior
|
|
46
|
+
- After finishing UI/API tasks, agent must complete commit + push + PR creation.
|
|
47
|
+
- Agent should return PR URL as final output for the task.
|