diff --git a/.claude/skills/git-workflow/SKILL.md b/.claude/skills/git-workflow/SKILL.md new file mode 100644 index 0000000..fa47830 --- /dev/null +++ b/.claude/skills/git-workflow/SKILL.md @@ -0,0 +1,168 @@ +--- +name: git-workflow +description: Enforce repository git workflow with platform-aware operations for GitHub (`gh`) and GitLab (`glab`), including branch naming, conventional commits, PR/MR creation and review, and issue creation using detected templates from `.github/` or `.gitlab/`. Use when handling branches, commits, pull/merge requests, reviews, or issue workflows. +--- + +# Git Workflow + +## Resolve Platform + +1. Detect platform in this order: + - Read `.copier/.copier-answers.yml` and use `git_platform` when present. + - Use repo markers: `.github/` -> `github`, `.gitlab/` -> `gitlab`. + - Parse `git remote get-url origin`: + - contains `github` -> `github` + - contains `gitlab` -> `gitlab` + - Fallback to `github`. +2. Select CLI: + - `github` -> `gh` + - `gitlab` -> `glab` +3. Verify CLI and auth before platform operations: + - `command -v gh && gh auth status` + - `command -v glab && glab auth status` +4. If selected CLI is unavailable, continue local git operations and ask user to finish remote operations manually. + +## Detect Templates + +### GitHub Paths + +1. Pull request template candidates in priority order: + - `.github/pull_request_template.md` + - `.github/PULL_REQUEST_TEMPLATE.md` + - `.github/PULL_REQUEST_TEMPLATE/*.md` (alphabetical) +2. Issue template candidates: + - `.github/ISSUE_TEMPLATE/*.md` (alphabetical, ignore `config.yml`) + +### GitLab Paths + +1. Merge request template candidates: + - `.gitlab/merge_request_templates/*.md` (alphabetical) +2. Issue template candidates: + - `.gitlab/issue_templates/*.md` (alphabetical) + +### Template Rendering Rules + +1. Strip YAML frontmatter (`--- ... ---`) from issue templates before submitting. +2. Remove placeholder HTML comments (``). +3. Keep original section headings and checklist items. +4. Fill sections from context: + - Related issue: `Closes #` + - Summary/proposed solution: concise bullets from current changes + - Breaking changes: `N/A` when none +5. If no template exists, use a fallback body with: + - Related issue + - Summary of changes + - Breaking changes + - Checklist + +## Branch Workflow + +1. Require issue-first workflow before opening PR/MR. +2. Create branch names as `/-`. +3. Use branch types: + - `feat` + - `fix` + - `refactor` + - `docs` + - `chore` + - `test` +4. Prefer `feat|fix|refactor` for branch-triggered CI compatibility in this repo. + +```bash +git fetch origin +git checkout -b feat/- +``` + +## Commit Workflow + +1. Enforce Conventional Commits: + - `(): ` +2. Use commit types: + - `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `ci`, `build`, `perf`, `revert` +3. Keep subject imperative and concise. +4. Add issue linkage in body when available (`Refs #`). + +```bash +git add -A +git commit -m "(): " -m "Refs #" +``` + +## Create PR Or MR + +1. Render template into a temporary body file. +2. Use a title aligned with commit subject. +3. Include issue linkage in body. +4. Create request with platform CLI. + +### GitHub + +```bash +gh pr create --title "(): " --body-file .git/PR_BODY.md --base main +``` + +### GitLab + +```bash +glab mr create --title "(): " --description "$(cat .git/PR_BODY.md)" --target-branch main --source-branch "$(git branch --show-current)" --yes +``` + +## Review PR Or MR + +### GitHub + +```bash +gh pr view +gh pr checks +gh pr review --approve +gh pr review --request-changes --body "Please address requested changes." +``` + +### GitLab + +```bash +glab mr view +glab ci status +glab mr approve +glab mr note -m "Request changes: please address reviewer feedback." +``` + +Use `glab mr note` as the request-changes action in GitLab workflows. + +## Create Issues With Templates + +1. Select issue template by intent: + - bug -> first match containing `bug` + - feature -> first match containing `feature` + - fallback -> first available template +2. Render template with concise, concrete sections. +3. Create issue with platform CLI. + +### GitHub + +```bash +gh issue create --title "" --body-file .git/ISSUE_BODY.md +``` + +### GitLab + +```bash +glab issue create --title "" --description "$(cat .git/ISSUE_BODY.md)" --yes +``` + +## Merge Workflow + +1. Verify checks/pipeline status before merge. +2. Keep merge strategy consistent with repository preferences. +3. Ensure linked issue is present before merge. + +### GitHub + +```bash +gh pr merge --squash +``` + +### GitLab + +```bash +glab mr merge --squash --yes +``` diff --git a/.copier/post_copy.py b/.copier/post_copy.py index 213d1cd..98d63ad 100644 --- a/.copier/post_copy.py +++ b/.copier/post_copy.py @@ -1,8 +1,10 @@ from pathlib import Path import shutil +import sys root = Path.cwd() copier_dir = root / ".copier" +git_platform = sys.argv[1] if len(sys.argv) > 1 else "github" for f in ["README.md", "pyproject.toml", ".env"]: src = copier_dir / f @@ -10,3 +12,8 @@ if src.exists(): dst.unlink(missing_ok=True) shutil.move(src, dst) + +if git_platform == "gitlab": + shutil.rmtree(root / ".github", ignore_errors=True) +else: + shutil.rmtree(root / ".gitlab", ignore_errors=True) diff --git a/.gitlab/issue_templates/bug_report.md b/.gitlab/issue_templates/bug_report.md new file mode 100644 index 0000000..5d1f247 --- /dev/null +++ b/.gitlab/issue_templates/bug_report.md @@ -0,0 +1,21 @@ +## Problem + + + +## Minimal Reproducible Example + +```python +# Provide code that reproduces the issue +``` + +## Expected vs Actual + +**Expected:** + +**Actual:** + +## Environment + +- Python version: +- Package version: +- OS: diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md new file mode 100644 index 0000000..6893474 --- /dev/null +++ b/.gitlab/issue_templates/feature_request.md @@ -0,0 +1,15 @@ +## Use Case + + + +## Proposed Solution + + + +## Alternatives Considered + + + +## Implementation Notes + + diff --git a/.gitlab/merge_request_templates/default.md b/.gitlab/merge_request_templates/default.md new file mode 100644 index 0000000..56967bb --- /dev/null +++ b/.gitlab/merge_request_templates/default.md @@ -0,0 +1,19 @@ +## Related Issue + +Closes # + +## Summary of Changes + + + +## Breaking Changes + + + +## Checklist + +- [ ] Issue discussion completed before opening MR +- [ ] Scope is small and focused (single feature/fix) +- [ ] All functions have full type annotations +- [ ] Async/await used for all I/O operations +- [ ] Tests added for new behaviors diff --git a/copier.yaml b/copier.yaml index 5bd8443..6e601b7 100644 --- a/copier.yaml +++ b/copier.yaml @@ -5,6 +5,18 @@ project_name: help: Project name default: my-backend-project +git_platform: + help: Git platform for workflow operations + choices: + - github + - gitlab + default: github + +init_git_repo: + type: bool + help: Initialize git repository with `git init` after project copy + default: true + development_database: help: Development database type choices: @@ -120,6 +132,9 @@ github_oauth_client_secret: _answers_file: .copier/.copier-answers.yml _tasks: - - command: ["{{ _copier_python }}", ".copier/post_copy.py"] + - command: ["git", "init"] + when: "{{ _copier_operation == 'copy' and init_git_repo }}" + description: Initialize Git Repository + - command: ["{{ _copier_python }}", ".copier/post_copy.py", "{{ git_platform }}"] when: "{{ _copier_operation == 'copy' }}" - description: Templates Overwrite \ No newline at end of file + description: Templates Overwrite