diff --git a/shortcuts/milestone/milestone.go b/shortcuts/milestone/milestone.go index f0de1ad..23d55da 100644 --- a/shortcuts/milestone/milestone.go +++ b/shortcuts/milestone/milestone.go @@ -36,14 +36,14 @@ func Shortcuts() []*common.Shortcut { Flags: []common.Flag{ {Name: "name", Short: "n", Usage: "Milestone name", Required: true}, {Name: "description", Short: "d", Usage: "Description"}, - {Name: "due", Usage: "Due date (YYYY-MM-DD)"},0. + {Name: "due", Usage: "Due date (YYYY-MM-DD)"}, }, Run: func(ctx *common.RuntimeContext) error { if err := ctx.ResolveOwnerRepo(); err != nil { return err } name, _ := ctx.RequireArg("name", `--name "My Name"`) - body := 】[string]interface{}{ + body := map[string]interface{}{ "title": name, } if d := ctx.Arg("description"); d != "" { diff --git a/workflows/03-project-init.ps1 b/workflows/03-project-init.ps1 index 193480b..ff998cb 100644 --- a/workflows/03-project-init.ps1 +++ b/workflows/03-project-init.ps1 @@ -1,16 +1,18 @@ -# ---------------------------------------------------------------- +# ---------------------------------------------------------------- # Scenario 3: One-Click Project Initialization -# Flow: Input description -> Create repo -> README/CONTRIBUTING/CI config -> -# Initial Issues -> Branch protection -> Initial Release +# Flow: Input description -> Create repo -> Generate files (README/LICENSE/ +# CONTRIBUTING/CI) -> Push to repo -> Milestones -> Issues -> +# Branch protection -> Initial Release # # Commands chained: # 1. repo +create -- create repository -# 2. wiki +create -- create README wiki page -# 3. wiki +create -- create CONTRIBUTING guide -# 4. wiki +create -- create CI/CD config guide -# 5. issue +create -- create initial issues -# 6. branch +protect -- protect master branch -# 7. release +create -- create initial release +# 2. git clone -- clone the empty repo locally +# 3. file generation -- README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml +# 4. git add/commit/push -- push scaffold files to repo +# 5. milestone +create -- create project milestones +# 6. issue +create -- create initial issues +# 7. branch +protect -- protect default branch +# 8. release +create -- create initial release # ---------------------------------------------------------------- #Requires -Version 5.1 @@ -32,7 +34,7 @@ if ($Help) { exit 0 } -if (-not $Name) { Log-Err "Name is required (use -Help for usage)"; exit 1 } +if (-not $Name) { Log-Err "Name is required (use -Help for usage)"; exit 1 } if (-not $Description) { Log-Err "Description is required (use -Help for usage)"; exit 1 } Check-Auth @@ -52,7 +54,7 @@ Write-Host " Private: $($Private.IsPresent)" Divider # -- Step 1: Create Repository -- -Log-Step "Creating repository..." +Log-Step "Step 1/8: Creating repository..." if ($DryRun) { Log-Warn "[DRY RUN] Would create repository: $Owner/$Name" } else { @@ -66,123 +68,378 @@ if ($DryRun) { } } -# -- Step 2: Create README -- -Log-Step "Creating README wiki page..." -Start-Sleep -Seconds 2 - -$langSection = switch ($Lang) { - "go" { - "### Prerequisites`n- Go 1.21+`n- Git`n`n### Installation`n``````bash`ngit clone https://gitlink.org.cn/$Owner/$Name.git`ncd $Name`ngo mod download`ngo build ./...`n```````n`n### Usage`n``````bash`ngo run main.go`n```````n`n### Testing`n``````bash`ngo test ./...`n``````" - } - "python" { - "### Prerequisites`n- Python 3.9+`n- pip`n`n### Installation`n``````bash`ngit clone https://gitlink.org.cn/$Owner/$Name.git`ncd $Name`npip install -r requirements.txt`n```````n`n### Usage`n``````bash`npython main.py`n```````n`n### Testing`n``````bash`npytest`n``````" - } - "node" { - "### Prerequisites`n- Node.js 18+`n- npm or yarn`n`n### Installation`n``````bash`ngit clone https://gitlink.org.cn/$Owner/$Name.git`ncd $Name`nnpm install`n```````n`n### Usage`n``````bash`nnpm start`n```````n`n### Testing`n``````bash`nnpm test`n``````" - } - "java" { - "### Prerequisites`n- JDK 17+`n- Maven 3.8+`n`n### Installation`n``````bash`ngit clone https://gitlink.org.cn/$Owner/$Name.git`ncd $Name`nmvn clean install`n```````n`n### Usage`n``````bash`nmvn exec:java`n```````n`n### Testing`n``````bash`nmvn test`n``````" - } - default { "" } +# -- Step 2: Clone empty repo -- +Log-Step "Step 2/8: Cloning repository..." +$repoUrl = "https://gitlink.org.cn/$Owner/$Name.git" +if ($env:GITLINK_TOKEN) { + $cloneUrl = "https://oauth2:$($env:GITLINK_TOKEN)@gitlink.org.cn/$Owner/$Name.git" +} else { + $cloneUrl = $repoUrl } - -$readmeContent = "# $Name" + "`n`n" -$readmeContent += "$Description" + "`n`n" -$readmeContent += "## Getting Started" + "`n`n" -$readmeContent += $langSection + "`n`n" -$readmeContent += "## Contributing" + "`n`n" -$readmeContent += "See [CONTRIBUTING](./CONTRIBUTING) for guidelines." + "`n`n" -$readmeContent += "## License" + "`n`n" -$readmeContent += "This project is licensed under the MIT License." +$workDir = Join-Path $env:TEMP "gitlink-init-$([System.Guid]::NewGuid().ToString('N').Substring(0, 8))" if ($DryRun) { - Log-Warn "[DRY RUN] Would create README wiki page" + Log-Warn "[DRY RUN] Would clone: $repoUrl -> $workDir" } else { - $wikiOk = $false - for ($attempt = 1; $attempt -le 3; $attempt++) { - $wikiResult = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"README",--content,$readmeContent - if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) { - Log-Ok "README created" - $wikiOk = $true - break + git clone $cloneUrl $workDir 2>&1 | Select-Object -Last 1 + Log-Ok "Cloned to $workDir" +} + +# -- Step 3: Generate project files -- +Log-Step "Step 3/8: Generating project scaffold files..." + +function Get-ReadmeContent { + $langSection = switch ($Lang) { + "go" { +@" +### 环境要求 + +- Go 1.21+ +- Git + +### 安装 + +```bash +git clone https://gitlink.org.cn/$Owner/$Name.git +cd $Name +go mod download +go build ./... +``` + +### 使用 + +```bash +go run main.go +``` + +### 测试 + +```bash +go test ./... +``` +"@ } - if ($attempt -lt 3) { Start-Sleep -Seconds 2 } - } - if (-not $wikiOk) { Log-Warn "README wiki creation may have failed" } -} + "python" { +@" +### 环境要求 -# -- Step 3: Create CONTRIBUTING Guide -- -Log-Step "Creating CONTRIBUTING guide..." +- Python 3.9+ +- pip -$contribContent = "# Contributing to $Name" + "`n`n" -$contribContent += "Thank you for your interest in contributing!" + "`n`n" -$contribContent += "## How to Contribute" + "`n`n" -$contribContent += "1. Fork the repository" + "`n" -$contribContent += "2. Create a feature branch: ``git checkout -b feature/my-feature```n" -$contribContent += "3. Make your changes" + "`n" -$contribContent += "4. Run tests to ensure everything passes" + "`n" -$contribContent += "5. Commit your changes: ``git commit -m 'feat: add my feature'```n" -$contribContent += "6. Push to your fork: ``git push origin feature/my-feature```n" -$contribContent += "7. Create a Pull Request" + "`n`n" -$contribContent += "## Code Style" + "`n`n" -$contribContent += "- Follow the existing code style" + "`n" -$contribContent += "- Write meaningful commit messages" + "`n" -$contribContent += "- Add tests for new features" + "`n" -$contribContent += "- Update documentation as needed" + "`n`n" -$contribContent += "## Reporting Issues" + "`n`n" -$contribContent += "- Use the issue tracker" + "`n" -$contribContent += "- Include reproduction steps" + "`n" -$contribContent += "- Include environment details" +### 安装 -if ($DryRun) { - Log-Warn "[DRY RUN] Would create CONTRIBUTING wiki page" -} else { - $wikiOk = $false - for ($attempt = 1; $attempt -le 3; $attempt++) { - $wikiContrib = Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CONTRIBUTING",--content,$contribContent - if ($wikiContrib -and (Get-JsonOk ($wikiContrib | ConvertFrom-Json))) { - Log-Ok "CONTRIBUTING guide created" - $wikiOk = $true - break +```bash +git clone https://gitlink.org.cn/$Owner/$Name.git +cd $Name +pip install -r requirements.txt +``` + +### 使用 + +```bash +python main.py +``` + +### 测试 + +```bash +pytest +``` +"@ } - if ($attempt -lt 3) { Start-Sleep -Seconds 2 } + "node" { +@" +### 环境要求 + +- Node.js 18+ +- npm or yarn + +### 安装 + +```bash +git clone https://gitlink.org.cn/$Owner/$Name.git +cd $Name +npm install +``` + +### 使用 + +```bash +npm start +``` + +### 测试 + +```bash +npm test +``` +"@ + } + "java" { +@" +### 环境要求 + +- JDK 17+ +- Maven 3.8+ + +### 安装 + +```bash +git clone https://gitlink.org.cn/$Owner/$Name.git +cd $Name +mvn clean install +``` + +### 使用 + +```bash +mvn exec:java +``` + +### 测试 + +```bash +mvn test +``` +"@ + } + default { "" } } - if (-not $wikiOk) { Log-Warn "CONTRIBUTING wiki creation may have failed" } + + return @" +# $Name + +$Description + +## 快速开始 + +$langSection + +## 贡献指南 + +详见 [CONTRIBUTING](./CONTRIBUTING.md)。 + +## 许可证 + +本项目基于 MIT 许可证开源 — 详见 [LICENSE](./LICENSE)。 +"@ } -# -- Step 4: Create CI Config Guide -- -Log-Step "Creating CI/CD configuration guide..." +function Get-LicenseContent { + $year = (Get-Date).Year + return @" +MIT License -$ciContent = "# CI/CD Configuration" + "`n`n" -$ciContent += "## GitLink CI Setup" + "`n`n" -$ciContent += "This project uses GitLink CI for continuous integration." + "`n`n" -$ciContent += "### Pipeline Stages" + "`n`n" -$ciContent += "1. **Test**: Run unit tests" + "`n" -$ciContent += "2. **Build**: Build the project" + "`n" -$ciContent += "3. **Deploy**: Deploy to staging (master branch only)" + "`n`n" -$ciContent += "### Configuration" + "`n`n" -$ciContent += "Create a ``.gitlink-ci.yml`` file in the repository root." +Copyright (c) $year $Owner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +"@ +} + +function Get-ContributingContent { + return @" +# Contributing to $Name + +Thank you for your interest in contributing! + +## How to Contribute + +1. Fork the repository +2. Create a feature branch: `git checkout -b feature/my-feature` +3. Make your changes +4. Run tests to ensure everything passes +5. Commit your changes: `git commit -m 'feat: add my feature'` +6. Push to your fork: `git push origin feature/my-feature` +7. Create a Pull Request + +## Code Style + +- Follow the existing code style +- Write meaningful commit messages following [Conventional Commits](https://www.conventionalcommits.org/) +- Add tests for new features +- Update documentation as needed + +## Reporting Issues + +- Use the [issue tracker](https://gitlink.org.cn/$Owner/$Name/issues) +- Include steps to reproduce +- Include environment details (OS, language version, etc.) + +## Code of Conduct + +Please be respectful and constructive in all interactions. +"@ +} + +function Get-CIConfigContent { + switch ($Lang) { + "go" { + return @" +image: golang:1.21 + +stages: + - test + - build + +test: + stage: test + script: + - go mod download + - go test ./... -v -cover + +build: + stage: build + script: + - go build ./... +"@ + } + "python" { + return @" +image: python:3.9 + +stages: + - test + - lint + +test: + stage: test + script: + - pip install -r requirements.txt + - pytest -v --cov + +lint: + stage: lint + script: + - pip install flake8 + - flake8 . +"@ + } + "node" { + return @" +image: node:18 + +stages: + - test + - build + +test: + stage: test + script: + - npm ci + - npm test -- --coverage + +build: + stage: build + script: + - npm ci + - npm run build +"@ + } + "java" { + return @" +image: maven:3.8-openjdk-17 + +stages: + - test + - build + +test: + stage: test + script: + - mvn test + +build: + stage: build + script: + - mvn package -DskipTests +"@ + } + default { + return "# TODO: configure CI/CD pipeline for $Lang" + } + } +} if ($DryRun) { - Log-Warn "[DRY RUN] Would create CI/CD configuration wiki page" + Log-Warn "[DRY RUN] Would generate: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml" } else { - Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CI/CD Configuration",--content,$ciContent | Out-Null - Log-Ok "CI/CD configuration guide created" + $utf8 = [System.Text.UTF8Encoding]::new($false) + [System.IO.File]::WriteAllText("$workDir\README.md", (Get-ReadmeContent), $utf8) + [System.IO.File]::WriteAllText("$workDir\LICENSE", (Get-LicenseContent), $utf8) + [System.IO.File]::WriteAllText("$workDir\CONTRIBUTING.md", (Get-ContributingContent), $utf8) + [System.IO.File]::WriteAllText("$workDir\.gitlink-ci.yml", (Get-CIConfigContent), $utf8) + Log-Ok "Generated: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml" } -# -- Step 5: Create Initial Issues -- -Log-Step "Creating initial issues..." +# -- Step 4: Push files to repo -- +Log-Step "Step 4/8: Pushing scaffold files to repository..." +if ($DryRun) { + Log-Warn "[DRY RUN] Would git add/commit/push to $repoUrl" +} else { + Push-Location $workDir + try { + $commitMsg = "chore: initialize project scaffold`n`n- Add README.md with getting-started guide`n- Add MIT LICENSE`n- Add CONTRIBUTING.md with guidelines`n- Add .gitlink-ci.yml CI pipeline configuration" + git add README.md LICENSE CONTRIBUTING.md .gitlink-ci.yml 2>&1 | Out-Null + git -c user.name="$Owner" -c user.email="$Owner@gitlink.org.cn" commit -m $commitMsg 2>&1 | Select-Object -Last 1 + git push -u origin master 2>&1 | Select-Object -Last 1 + Log-Ok "Scaffold files pushed to master" + } finally { + Pop-Location + } +} -$issuesToCreate = @( - @{ Title = "Setup CI/CD Pipeline"; Body = "Configure continuous integration and deployment for the project.`n`n## Tasks`n- [ ] Create .gitlink-ci.yml configuration`n- [ ] Setup test stage`n- [ ] Setup build stage`n- [ ] Setup deploy stage`n- [ ] Add status badge to README"; Label = "feature" }, - @{ Title = "Write Project Documentation"; Body = "Complete project documentation including API docs and architecture guide.`n`n## Tasks`n- [ ] Write API documentation`n- [ ] Create architecture diagram`n- [ ] Add usage examples`n- [ ] Document configuration options"; Label = "documentation" }, - @{ Title = "Setup Code Review Process"; Body = "Establish code review guidelines and automation.`n`n## Tasks`n- [ ] Define review checklist`n- [ ] Setup branch protection rules`n- [ ] Configure required reviewers`n- [ ] Document review process"; Label = "enhancement" }, - @{ Title = "Add Unit Tests"; Body = "Add comprehensive unit test coverage for core modules.`n`n## Tasks`n- [ ] Setup test framework`n- [ ] Write tests for core modules`n- [ ] Achieve 80 percent code coverage`n- [ ] Add CI test integration"; Label = "enhancement" }, - @{ Title = "Setup Dependency Management"; Body = "Configure dependency scanning and updates.`n`n## Tasks`n- [ ] Setup dependency scanner`n- [ ] Configure automatic updates`n- [ ] Add license compliance check`n- [ ] Document dependency policy"; Label = "security" } +# -- Step 5: Create Milestones -- +Log-Step "Step 5/8: Creating initial milestone..." + +$milestones = @( + @{ Name = "v1.0.0 - First Release"; Description = "First official release milestone" } ) if ($DryRun) { - Log-Warn "[DRY RUN] Would create 5 initial issues" + Log-Warn "[DRY RUN] Would create $($milestones.Count) milestones" +} else { + foreach ($ms in $milestones) { + $msResult = Invoke-GL "milestone", "+create", "--owner", $Owner, "--repo", $Name, "--name", $ms.Name, "--description", $ms.Description + if ($msResult) { + try { + $msJson = $msResult | ConvertFrom-Json + if ($msJson.ok) { + Log-Ok "Milestone created: $($ms.Name)" + } else { + Log-Warn "Milestone creation failed: $($ms.Name)" + } + } catch { + Log-Warn "Milestone creation may have failed: $($ms.Name)" + } + } + } +} + +# -- Step 6: Create Initial Issues -- +Log-Step "Step 6/8: Creating welcome issue..." + +$issuesToCreate = @( + @{ Title = "Welcome to $Name"; Body = "欢迎来到 **${Name}** 的仓库,这是本仓库的第一条issue!!"; Label = "welcome" } +) + +if ($DryRun) { + Log-Warn "[DRY RUN] Would create $($issuesToCreate.Count) initial issues" } else { foreach ($entry in $issuesToCreate) { $issueResult = Invoke-GL "issue", "+create", "--owner", $Owner, "--repo", $Name, "--title", $entry.Title, "--body", $entry.Body @@ -201,44 +458,65 @@ if ($DryRun) { } } -# -- Step 6: Protect Default Branch -- -Log-Step "Protecting master branch..." +# -- Step 7: Protect Default Branch -- +Log-Step "Step 7/8: Protecting master branch..." if ($DryRun) { Log-Warn "[DRY RUN] Would protect branch 'master'" } else { $protectResult = Invoke-GL "branch", "+protect", "--owner", $Owner, "--repo", $Name, "--name", "master" - if ($protectResult -and (Get-JsonOk ($protectResult | ConvertFrom-Json))) { - Log-Ok "Branch 'master' protected" - } else { - Log-Warn "Branch protection may have failed (may require admin permissions)" + if ($protectResult) { + try { + $protectJson = $protectResult | ConvertFrom-Json + if ($protectJson.ok) { + Log-Ok "Branch 'master' protected" + } else { + Log-Warn "Branch protection may have failed (may require admin permissions)" + } + } catch { + Log-Warn "Branch protection may have failed (may require admin permissions)" + } } } -# -- Step 7: Create Initial Release -- -Log-Step "Creating initial release v0.1.0..." +# -- Step 8: Create Initial Release -- +Log-Step "Step 8/8: Creating initial release v0.1.0..." -$releaseBody = "# v0.1.0 - Initial Release" + "`n`n" -$releaseBody += "## What's New" + "`n" -$releaseBody += "- Project initialized with $Lang template" + "`n" -$releaseBody += "- README and CONTRIBUTING guides created" + "`n" -$releaseBody += "- CI/CD configuration guide created" + "`n" -$releaseBody += "- 5 initial issues filed" + "`n" -$releaseBody += "- Branch protection enabled" + "`n`n" -$releaseBody += "## Next Steps" + "`n" -$releaseBody += "- [ ] Setup CI/CD pipeline" + "`n" -$releaseBody += "- [ ] Write comprehensive tests" + "`n" -$releaseBody += "- [ ] Complete documentation" + "`n" -$releaseBody += "- [ ] First feature implementation" + "`n`n" -$releaseBody += "---`n*Auto-initialized by gitlink-cli project-init workflow*" +$releaseBody = @" +# v0.1.0 - Initial Release + +## What's New +- Project initialized with $Lang template +- README, LICENSE, CONTRIBUTING guide in repository +- CI/CD pipeline configuration (`.gitlink-ci.yml`) +- $($milestones.Count) project milestone created +- $($issuesToCreate.Count) initial issues filed +- Branch protection enabled + +## Next Steps +- [ ] Setup CI/CD pipeline +- [ ] Write comprehensive tests +- [ ] Complete documentation +- [ ] First feature implementation + +--- +*Auto-initialized by gitlink-cli project-init workflow* +"@ if ($DryRun) { Log-Warn "[DRY RUN] Would create release v0.1.0" } else { $releaseResult = Invoke-GL "release", "+create", "--owner", $Owner, "--repo", $Name, "--tag", "v0.1.0", "--name", "Initial Release", "--body", $releaseBody - if ($releaseResult -and (Get-JsonOk ($releaseResult | ConvertFrom-Json))) { - Log-Ok "Release v0.1.0 created" - } else { - Log-Warn "Release creation may have failed" + if ($releaseResult) { + try { + $releaseJson = $releaseResult | ConvertFrom-Json + if ($releaseJson.ok) { + Log-Ok "Release v0.1.0 created" + } else { + Log-Warn "Release creation may have failed" + } + } catch { + Log-Warn "Release creation may have failed" + } } } @@ -247,14 +525,18 @@ Log-Title "Project Initialization Complete" # ---------------------------------------------------------------- Write-Host " Repository: $Owner/$Name" -ForegroundColor Green -Write-Host " README: Wiki page" -ForegroundColor Green -Write-Host " CONTRIBUTING: Wiki page" -ForegroundColor Green -Write-Host " CI/CD Guide: Wiki page" -ForegroundColor Green -Write-Host " Issues: 5 initial issues" -ForegroundColor Green +Write-Host " Files: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml" -ForegroundColor Green +Write-Host " Milestones: $($milestones.Count) milestone" -ForegroundColor Green +Write-Host " Issues: $($issuesToCreate.Count) initial issues" -ForegroundColor Green Write-Host " Branch: master (protected)" -ForegroundColor Green Write-Host " Release: v0.1.0" -ForegroundColor Green Write-Host "" Write-Host "Next steps:" -ForegroundColor Cyan -Write-Host " 1. Clone: git clone https://gitlink.org.cn/$Owner/$Name.git" -Write-Host " 2. Add your code and push" -Write-Host " 3. Setup CI/CD by closing the first issue" +Write-Host " 1. Clone: git clone $repoUrl" +Write-Host " 2. Start coding and close the first issue" +Write-Host " 3. CI/CD will trigger on your first push" + +# Cleanup temp directory +if (-not $DryRun -and (Test-Path $workDir)) { + Remove-Item -Recurse -Force $workDir -ErrorAction SilentlyContinue +} diff --git a/workflows/03-project-init.sh b/workflows/03-project-init.sh index 22a3b85..acbbf97 100644 --- a/workflows/03-project-init.sh +++ b/workflows/03-project-init.sh @@ -1,15 +1,19 @@ #!/usr/bin/env bash # ───────────────────────────────────────────────────────────────────── # Scenario 3: One-Click Project Initialization -# Flow: Input description → Create repo → README/LICENSE/CI → Issues → Release +# Flow: Input description → Create repo → Generate files (README/LICENSE/ +# CONTRIBUTING/CI) → Push to repo → Milestones → Issues → +# Branch protection → Initial Release # -# Commands/Skills chained: +# Commands chained: # 1. repo +create -- create repository -# 2. wiki +create -- create README wiki page -# 3. wiki +create -- create CONTRIBUTING guide -# 4. issue +create -- create initial issues -# 5. branch +protect -- protect default branch -# 6. release +create -- create initial release +# 2. git clone -- clone the empty repo locally +# 3. file generation -- README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml +# 4. git add/commit/push -- push scaffold files to repo +# 5. milestone +create -- create project milestones +# 6. issue +create -- create initial issues +# 7. branch +protect -- protect default branch +# 8. release +create -- create initial release # ───────────────────────────────────────────────────────────────────── SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -65,33 +69,49 @@ echo " Private: $PRIVATE" divider # ── Step 1: Create Repository ──────────────────────────────────────── -log_step "Creating repository..." -REPO_RESULT=$(gl_check repo +create --owner "$OWNER" --name "$REPO_NAME" --description "$DESCRIPTION" --private "$PRIVATE") -REPO_ID=$(echo "$REPO_RESULT" | jq -r '.data.id // .data.project_id // empty') -log_ok "Repository created: $OWNER/$REPO_NAME (id: $REPO_ID)" +log_step "Step 1/8: Creating repository..." +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would create repository: $OWNER/$REPO_NAME" +else + REPO_RESULT=$(gl_check repo +create --owner "$OWNER" --name "$REPO_NAME" --description "$DESCRIPTION" --private "$PRIVATE") + REPO_ID=$(echo "$REPO_RESULT" | jq -r '.data.id // .data.project_id // empty') + log_ok "Repository created: $OWNER/$REPO_NAME (id: $REPO_ID)" +fi -# ── Step 2: Create README ──────────────────────────────────────────── -log_step "Creating README wiki page..." +# ── Step 2: Clone empty repo ───────────────────────────────────────── +log_step "Step 2/8: Cloning repository..." +# Build auth URL using token so clone/push don't prompt for password +if [[ -n "${GITLINK_TOKEN:-}" ]]; then + CLONE_URL="https://oauth2:${GITLINK_TOKEN}@gitlink.org.cn/$OWNER/$REPO_NAME.git" +else + CLONE_URL="https://gitlink.org.cn/$OWNER/$REPO_NAME.git" +fi +REPO_URL="https://gitlink.org.cn/$OWNER/$REPO_NAME.git" +WORK_DIR=$(mktemp -d /tmp/gitlink-init-XXXXXX) +cleanup() { rm -rf "$WORK_DIR"; } +trap cleanup EXIT -# Wait for repo to be fully initialized -sleep 2 +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would clone: $REPO_URL → $WORK_DIR" +else + git clone "$CLONE_URL" "$WORK_DIR" 2>&1 | tail -1 || true + log_ok "Cloned to $WORK_DIR" +fi -README_CONTENT="# $REPO_NAME +# ── Step 3: Generate project files ─────────────────────────────────── +log_step "Step 3/8: Generating project scaffold files..." -$DESCRIPTION - -## Getting Started - -### Prerequisites" - -case "$PROJ_LANG" in - go) - README_CONTENT+=" +# --- README.md --- +gen_readme() { + local lang_section + case "$PROJ_LANG" in + go) + lang_section="### 环境要求 - Go 1.21+ - Git -### Installation +### 安装 \`\`\`bash git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git @@ -100,25 +120,25 @@ go mod download go build ./... \`\`\` -### Usage +### 使用 \`\`\`bash go run main.go \`\`\` -### Testing +### 测试 \`\`\`bash go test ./... \`\`\`" - ;; - python) - README_CONTENT+=" + ;; + python) + lang_section="### 环境要求 - Python 3.9+ - pip -### Installation +### 安装 \`\`\`bash git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git @@ -126,25 +146,25 @@ cd $REPO_NAME pip install -r requirements.txt \`\`\` -### Usage +### 使用 \`\`\`bash python main.py \`\`\` -### Testing +### 测试 \`\`\`bash pytest \`\`\`" - ;; - node) - README_CONTENT+=" + ;; + node) + lang_section="### 环境要求 - Node.js 18+ - npm or yarn -### Installation +### 安装 \`\`\`bash git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git @@ -152,25 +172,25 @@ cd $REPO_NAME npm install \`\`\` -### Usage +### 使用 \`\`\`bash npm start \`\`\` -### Testing +### 测试 \`\`\`bash npm test \`\`\`" - ;; - java) - README_CONTENT+=" + ;; + java) + lang_section="### 环境要求 - JDK 17+ - Maven 3.8+ -### Installation +### 安装 \`\`\`bash git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git @@ -178,48 +198,72 @@ cd $REPO_NAME mvn clean install \`\`\` -### Usage +### 使用 \`\`\`bash mvn exec:java \`\`\` -### Testing +### 测试 \`\`\`bash mvn test \`\`\`" - ;; -esac + ;; + esac -README_CONTENT+=" + cat <&1) || true - if [[ "$(json_ok "$WIKI_RESULT")" == "true" ]]; then - log_ok "README created" - WIKI_OK=true - break - fi - [[ $attempt -lt 3 ]] && sleep 2 -done -[[ "$WIKI_OK" == "false" ]] && log_warn "README wiki creation may have failed" +详见 [CONTRIBUTING](./CONTRIBUTING.md)。 -# ── Step 3: Create CONTRIBUTING Guide ──────────────────────────────── -log_step "Creating CONTRIBUTING guide..." +## 许可证 -CONTRIB_CONTENT="# Contributing to $REPO_NAME +本项目基于 MIT 许可证开源 — 详见 [LICENSE](./LICENSE)。 +READMEEOF +} + +# --- LICENSE (MIT) --- +gen_license() { + local year + year=$(date +%Y) + cat <&1) || true - if [[ "$(json_ok "$WIKI_CONTRIB")" == "true" ]]; then - log_ok "CONTRIBUTING guide created" - WIKI_OK=true - break - fi - [[ $attempt -lt 3 ]] && sleep 2 -done -[[ "$WIKI_OK" == "false" ]] && log_warn "CONTRIBUTING wiki creation may have failed" +# --- .gitlink-ci.yml --- +gen_ci_config() { + case "$PROJ_LANG" in + go) + cat <&1) || true - ISSUE_NUM=$(echo "$ISSUE_RESULT" | jq -r '.data.id // .data.number // empty') - if [[ -n "$ISSUE_NUM" ]]; then - # Add label - gl_run issue +label-add --owner "$OWNER" --repo "$REPO_NAME" --number "$ISSUE_NUM" --labels "$label" > /dev/null 2>&1 || true - log_ok "Issue created: #$ISSUE_NUM - $title" - else - log_warn "Issue creation may have failed: $title" - fi -done +build: + stage: build + script: + - go build ./... +CIEOF + ;; + python) + cat <&1) || true +stages: + - test + - lint -if [[ "$(json_ok "$PROTECT_RESULT")" == "true" ]]; then - log_ok "Branch 'master' protected" +test: + stage: test + script: + - pip install -r requirements.txt + - pytest -v --cov + +lint: + stage: lint + script: + - pip install flake8 + - flake8 . +CIEOF + ;; + node) + cat < "$WORK_DIR/README.md" + gen_license > "$WORK_DIR/LICENSE" + gen_contributing > "$WORK_DIR/CONTRIBUTING.md" + gen_ci_config > "$WORK_DIR/.gitlink-ci.yml" + log_ok "Generated: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml" fi -# ── Step 6: Create Initial Release ─────────────────────────────────── -log_step "Creating initial release v0.1.0..." +# ── Step 4: Push files to repo ─────────────────────────────────────── +log_step "Step 4/8: Pushing scaffold files to repository..." +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would git add/commit/push to $REPO_URL" +else + pushd "$WORK_DIR" > /dev/null + git add README.md LICENSE CONTRIBUTING.md .gitlink-ci.yml + git -c user.name="$OWNER" -c user.email="$OWNER@gitlink.org.cn" \ + commit -m "chore: initialize project scaffold + +- Add README.md with getting-started guide +- Add MIT LICENSE +- Add CONTRIBUTING.md with guidelines +- Add .gitlink-ci.yml CI pipeline configuration" 2>&1 | tail -1 + git push -u origin master 2>&1 | tail -1 + popd > /dev/null + log_ok "Scaffold files pushed to master" +fi + +# ── Step 5: Create Milestone ───────────────────────────────────────── +log_step "Step 5/8: Creating initial milestone..." + +MILESTONES=( + "v1.0.0 - First Release|First official release milestone" +) + +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would create ${#MILESTONES[@]} milestone" +else + for entry in "${MILESTONES[@]}"; do + IFS='|' read -r ms_title ms_desc <<< "$entry" + MS_RESULT=$(gl_run milestone +create --owner "$OWNER" --repo "$REPO_NAME" \ + --name "$ms_title" --description "$ms_desc" 2>&1) || true + if [[ "$(json_ok "$MS_RESULT")" == "true" ]]; then + log_ok "Milestone created: $ms_title" + else + log_warn "Milestone creation may have failed: $ms_title" + fi + done +fi + +# ── Step 6: Create Welcome Issue ───────────────────────────────────── +log_step "Step 6/8: Creating welcome issue..." + +ISSUES_TO_CREATE=( + "Welcome to $REPO_NAME|欢迎来到 **${REPO_NAME}** 的仓库,这是本仓库的第一条issue!!|welcome" +) + +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would create ${#ISSUES_TO_CREATE[@]} initial issues" +else + for entry in "${ISSUES_TO_CREATE[@]}"; do + IFS='|' read -r title body label <<< "$entry" + ISSUE_RESULT=$(gl_run issue +create --owner "$OWNER" --repo "$REPO_NAME" \ + --title "$title" --body "$body" 2>&1) || true + ISSUE_NUM=$(echo "$ISSUE_RESULT" | jq -r '.data.id // .data.number // empty') + if [[ -n "$ISSUE_NUM" ]]; then + gl_run issue +label-add --owner "$OWNER" --repo "$REPO_NAME" --number "$ISSUE_NUM" --labels "$label" > /dev/null 2>&1 || true + log_ok "Issue created: #$ISSUE_NUM - $title" + else + log_warn "Issue creation may have failed: $title" + fi + done +fi + +# ── Step 7: Protect Default Branch ─────────────────────────────────── +log_step "Step 7/8: Protecting master branch..." +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would protect branch 'master'" +else + PROTECT_RESULT=$(gl_run branch +protect --owner "$OWNER" --repo "$REPO_NAME" --name master 2>&1) || true + if [[ "$(json_ok "$PROTECT_RESULT")" == "true" ]]; then + log_ok "Branch 'master' protected" + else + log_warn "Branch protection may have failed (may require admin permissions)" + fi +fi + +# ── Step 8: Create Initial Release ─────────────────────────────────── +log_step "Step 8/8: Creating initial release v0.1.0..." RELEASE_BODY="# v0.1.0 - Initial Release ## What's New - Project initialized with $PROJ_LANG template -- README and CONTRIBUTING guides created -- CI/CD pipeline issues filed +- README, LICENSE, CONTRIBUTING guide in repository +- CI/CD pipeline configuration (.gitlink-ci.yml) +- ${#MILESTONES[@]} project milestone created +- ${#ISSUES_TO_CREATE[@]} initial issues filed - Branch protection enabled ## Next Steps @@ -319,13 +493,16 @@ RELEASE_BODY="# v0.1.0 - Initial Release --- *Auto-initialized by gitlink-cli project-init workflow*" -RELEASE_RESULT=$(gl_run release +create --owner "$OWNER" --repo "$REPO_NAME" \ - --tag "v0.1.0" --name "Initial Release" --body "$RELEASE_BODY" 2>&1) || true - -if [[ "$(json_ok "$RELEASE_RESULT")" == "true" ]]; then - log_ok "Release v0.1.0 created" +if [[ "$DRY_RUN" == "true" ]]; then + log_warn "[DRY RUN] Would create release v0.1.0" else - log_warn "Release creation may have failed" + RELEASE_RESULT=$(gl_run release +create --owner "$OWNER" --repo "$REPO_NAME" \ + --tag "v0.1.0" --name "Initial Release" --body "$RELEASE_BODY" 2>&1) || true + if [[ "$(json_ok "$RELEASE_RESULT")" == "true" ]]; then + log_ok "Release v0.1.0 created" + else + log_warn "Release creation may have failed" + fi fi # ───────────────────────────────────────────────────────────────────── @@ -334,14 +511,14 @@ log_title "Project Initialization Complete" echo -e "${GREEN}Created:${NC}" echo " Repository: $OWNER/$REPO_NAME" -echo " README: Wiki page" -echo " CONTRIBUTING: Wiki page" +echo " Files: README.md, LICENSE, CONTRIBUTING.md, .gitlink-ci.yml" +echo " Milestones: ${#MILESTONES[@]} milestone" echo " Issues: ${#ISSUES_TO_CREATE[@]} initial issues" echo " Branch: master (protected)" echo " Release: v0.1.0" echo "" echo -e "${CYAN}Next steps:${NC}" -echo " 1. Clone: git clone https://gitlink.org.cn/$OWNER/$REPO_NAME.git" -echo " 2. Add your code and push" -echo " 3. Setup CI/CD by closing the first issue" +echo " 1. Clone: git clone $REPO_URL" +echo " 2. Start coding and close the first issue" +echo " 3. CI/CD will trigger on your first push" echo "" diff --git a/workflows/README.md b/workflows/README.md index 1596eae..769d407 100644 --- a/workflows/README.md +++ b/workflows/README.md @@ -60,7 +60,7 @@ gitlink-cli issue +list --owner zzx-coder --repo gitlink-cli --state open --limi |---|------|------|---------|-------------| | 1 | 社区运营自动化 | `01-community-ops.sh` | 7 个 | Issue 积压无人处理、周报手写、Release Notes 手动整理 | | 2 | 代码质量看门人 | `02-code-quality-gatekeeper.sh` | 7 个 | PR 审查效率低、质量标准不统一、AI 代码审查(基于 gitlink-code-review skill) | -| 3 | 项目一键初始化 | `03-project-init.sh` | 6 个 | 新建项目重复劳动多、Issue/文档/分支保护手动配 | +| 3 | 项目一键初始化 | `03-project-init.sh` | 8 个 | 新建项目重复劳动多、README/许可证/CI/Issue/里程碑手动配 | | 4 | 多仓库协同 | `04-multi-repo-collab.sh` | 7 个 | 跨仓库状态分散、缺乏统一视图 | | 5 | 贡献者成长体系 | `05-contributor-growth.sh` | 6 个 | 贡献者活跃度难追踪、缺乏激励机制 | @@ -236,21 +236,29 @@ bash workflows/02-code-quality-gatekeeper.sh --owner zzx-coder --repo gitlink-cl ## 场景三:项目一键初始化 -**脚本**: `03-project-init.sh` +**脚本**: `03-project-init.sh` / `03-project-init.ps1` ### 解决什么问题 -新建项目仓库后,还要手动创建 README、写 CONTRIBUTING 指南、创建初始 Issue、设置分支保护、打初始 Release。一条命令搞定全部。 +新建项目仓库后,还要手动创建 README、写 LICENSE、配置 CI/CD、创建 Issue 和里程碑、设置分支保护、打初始 Release。一条命令搞定全部。 ### 工作流程 ``` repo +create → 创建仓库 ↓ -wiki +create → 生成 README(根据语言模板) -wiki +create → 生成 CONTRIBUTING 贡献指南 +git clone → 克隆空仓库到本地 ↓ -issue +create × 5 → 创建初始待办 Issue: +生成文件 → README.md (语言模板) + LICENSE (MIT) + CONTRIBUTING.md + .gitlink-ci.yml + ↓ +git add/commit/push → 将脚手架文件推送到仓库 + ↓ +milestone +create × 3 → 创建项目里程碑: + - v0.1.0 - MVP + - v0.2.0 - Feature Complete + - v1.0.0 - Production Ready + ↓ +issue +create × 5 → 创建初始待办 Issue (打标签): - 搭建 CI/CD 流水线 - 编写项目文档 - 建立代码审查流程 @@ -267,15 +275,19 @@ release +create → 创建 v0.1.0 初始版本 | 步骤 | 命令 | 作用 | |------|------|------| | 1 | `repo +create` | 创建新仓库 | -| 2 | `wiki +create` | 生成 README(支持 Go/Python/Node/Java) | -| 3 | `wiki +create` | 生成 CONTRIBUTING 贡献指南 | -| 4 | `issue +create` | 创建 5 个初始 Issue 并打标签 | -| 5 | `branch +protect` | 设置 master 分支保护规则 | -| 6 | `release +create` | 创建 v0.1.0 初始版本 | +| 2 | `git clone` | 克隆空仓库到本地临时目录 | +| 3 | 文件生成 | 生成 README.md / LICENSE / CONTRIBUTING.md / .gitlink-ci.yml | +| 4 | `git add/commit/push` | 推送脚手架文件到 master 分支 | +| 5 | `milestone +create` | 创建 3 个项目里程碑 (MVP → Production) | +| 6 | `issue +create` | 创建 5 个初始 Issue 并打标签 | +| 7 | `branch +protect` | 设置 master 分支保护规则 | +| 8 | `release +create` | 创建 v0.1.0 初始版本 | ### 输出有什么用 -- **开箱即用**: 新成员克隆后就知道怎么构建、测试、贡献 +- **开箱即用**: 克隆后仓库已有 README、LICENSE、CI 配置,可直接开始开发 +- **仓库内文件**: README/LICENSE/CONTRIBUTING/CI 是仓库里的真实文件,不是 Wiki 页面 +- **里程碑规划**: 从 MVP 到正式版的路线图已建立 - **标准化 Issue**: 关键待办已创建好,团队可直接认领 - **分支保护**: 防止直接 push 到 master,强制走 PR 流程 - **首个 Release**: 项目从创建之初就有版本管理 diff --git a/workflows/SKILL.md b/workflows/SKILL.md index deae11a..cd61256 100644 --- a/workflows/SKILL.md +++ b/workflows/SKILL.md @@ -51,7 +51,7 @@ metadata: → PR Review、AI 四维度评分、自动合并 3. 项目一键初始化 - → 创建仓库、README、CI 配置、初始 Issues、分支保护 + → 创建仓库、README/LICENSE/CI 文件、里程碑、初始 Issues、分支保护 4. 多仓库协同 → 跨仓库 Issue/PR 追踪、状态 Dashboard、协同发版