diff --git a/workflows/01-community-ops.ps1 b/workflows/01-community-ops.ps1 index 0ecf1562..a7ec5f21 100644 --- a/workflows/01-community-ops.ps1 +++ b/workflows/01-community-ops.ps1 @@ -1,6 +1,6 @@ -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- # Scenario 1: Community Operations Automation -# Flow: Issue auto-classify → Assign responsible → Weekly report → Release notes +# Flow: Issue auto-classify -> Assign responsible -> Weekly report -> Release notes # # Commands chained: # 1. issue +list -- fetch open issues @@ -10,7 +10,7 @@ # 5. pr +list -- collect merged PRs for weekly report # 6. wiki +create -- publish community weekly report # 7. release +create -- publish release notes -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- #Requires -Version 5.1 param( @@ -25,7 +25,7 @@ $ErrorActionPreference = "Stop" Import-Module "$PSScriptRoot/lib/common.psm1" -Force if ($Help) { - Write-Host "Usage: pwsh 01-community-ops.ps1 -Owner OWNER -Repo REPO [-WeeksAgo N] [-DryRun]" + Write-Host "Usage: powershell 01-community-ops.ps1 -Owner OWNER -Repo REPO [-WeeksAgo N] [-DryRun]" Write-Host "" Write-Host " -Owner OWNER Repository owner (org or user)" Write-Host " -Repo REPO Repository name" @@ -39,16 +39,14 @@ $r = Resolve-OwnerRepo $Owner $Repo $Owner = $r.Owner; $Repo = $r.Repo # Classification keywords -$Keywords = @{ - bug = @('bug','error','crash','fault','fix','修复','错误','异常','崩溃') - feature = @('feature','新增','建议','enhancement','add','support','功能') - question = @('how','怎么','如何','question','help','?','?') - documentation = @('doc','文档','readme','说明','guide') -} +$BugKw = @('bug','error','crash','fault','fix') +$FeatureKw = @('feature','enhancement','add','support','request') +$QuestionKw = @('how','question','help') +$DocsKw = @('doc','readme','guide','tutorial','example') -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Phase 1: Issue Auto-Classification" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Step "Fetching open issues..." $issuesJson = Invoke-GLCheck issue,+list,--owner,$Owner,--repo,$Repo,--state,open,--limit,100 @@ -65,30 +63,30 @@ if ($issueCount -gt 0) { foreach ($issue in $issues) { $id = $issue.id - $title = $issue.subject ?? $issue.title ?? "" - $desc = $issue.description ?? "" + $title = if ($issue.subject) { $issue.subject } elseif ($issue.title) { $issue.title } else { "" } + $desc = if ($issue.description) { $issue.description } else { "" } $combined = "$title $desc".ToLower() $classified = $false - foreach ($kw in $Keywords.bug) { - if ($combined -match [regex]::Escape($kw)) { $BugIds += $id; Log-Info " #$id → BUG: $title"; $classified = $true; break } + foreach ($kw in $BugKw) { + if ($combined -match [regex]::Escape($kw)) { $BugIds += $id; Log-Info " #$id -> BUG: $title"; $classified = $true; break } } if (-not $classified) { - foreach ($kw in $Keywords.feature) { - if ($combined -match [regex]::Escape($kw)) { $FeatureIds += $id; Log-Info " #$id → FEATURE: $title"; $classified = $true; break } + foreach ($kw in $FeatureKw) { + if ($combined -match [regex]::Escape($kw)) { $FeatureIds += $id; Log-Info " #$id -> FEATURE: $title"; $classified = $true; break } } } if (-not $classified) { - foreach ($kw in $Keywords.question) { - if ($combined -match [regex]::Escape($kw)) { $QuestionIds += $id; Log-Info " #$id → QUESTION: $title"; $classified = $true; break } + foreach ($kw in $QuestionKw) { + if ($combined -match [regex]::Escape($kw)) { $QuestionIds += $id; Log-Info " #$id -> QUESTION: $title"; $classified = $true; break } } } if (-not $classified) { - foreach ($kw in $Keywords.documentation) { - if ($combined -match [regex]::Escape($kw)) { $DocsIds += $id; Log-Info " #$id → DOCS: $title"; $classified = $true; break } + foreach ($kw in $DocsKw) { + if ($combined -match [regex]::Escape($kw)) { $DocsIds += $id; Log-Info " #$id -> DOCS: $title"; $classified = $true; break } } } - if (-not $classified) { Log-Info " #$id → UNCATEGORIZED: $title" } + if (-not $classified) { Log-Info " #$id -> UNCATEGORIZED: $title" } } Divider @@ -100,10 +98,10 @@ if ($issueCount -gt 0) { # Apply labels $labelGroups = @( - @{ Ids = $BugIds; Label = "bug" }, + @{ Ids = $BugIds; Label = "bug" }, @{ Ids = $FeatureIds; Label = "feature" }, @{ Ids = $QuestionIds; Label = "question" }, - @{ Ids = $DocsIds; Label = "documentation" } + @{ Ids = $DocsIds; Label = "documentation" } ) foreach ($g in $labelGroups) { if ($g.Ids.Count -gt 0) { @@ -116,9 +114,9 @@ if ($issueCount -gt 0) { } } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Phase 2: Assign Responsible Persons" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Step "Fetching repo members..." $membersJson = Invoke-GL repo,+members,--owner,$Owner,--repo,$Repo,--limit,50 @@ -131,7 +129,7 @@ if ($membersJson) { $memberLogins = @() foreach ($m in $members) { - $login = $m.login ?? $m.username + $login = if ($m.login) { $m.login } elseif ($m.username) { $m.username } else { $null } if ($login) { $memberLogins += $login } } @@ -142,8 +140,9 @@ if ($memberLogins.Count -gt 0) { $idx = 0 foreach ($id in $assignIds) { $assignee = $memberLogins[$idx % $memberLogins.Count] - Invoke-GL api,PATCH,"/v1/$Owner/$Repo/issues/$id",--body,"{`"assigned_to_id`": `"$assignee`"}" | Out-Null - Log-Info " Assigned #$id → @$assignee" + $bodyJson = "{`"assigned_to_id`": `"$assignee`"}" + Invoke-GL api,PATCH,"/v1/$Owner/$Repo/issues/$id",--body,$bodyJson | Out-Null + Log-Info " Assigned #$id -> @$assignee" $idx++ } Log-Ok "Assignment complete" @@ -152,9 +151,9 @@ if ($memberLogins.Count -gt 0) { Log-Warn "No repo members found, skipping assignment" } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Phase 3: Generate Community Weekly Report" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- $weekStart = (Get-Date).AddDays(-$WeeksAgo * 7).ToString("yyyy-MM-dd") $weekEnd = Get-DateToday @@ -178,29 +177,23 @@ $newIssuesCount = $issueCount $totalClassified = $BugIds.Count + $FeatureIds.Count + $QuestionIds.Count + $DocsIds.Count $reportTitle = "Community Weekly Report: $weekStart ~ $weekEnd" -$reportBody = @" -# $reportTitle - -## Summary -- New Issues: **$newIssuesCount** -- Closed Issues: **$closedCount** -- Merged PRs: **$mergedCount** - -## Issue Classification -| Type | Count | -|------|-------| -| Bug | $($BugIds.Count) | -| Feature | $($FeatureIds.Count) | -| Question | $($QuestionIds.Count) | -| Docs | $($DocsIds.Count) | - -## Highlights -- Auto-classified and labeled $totalClassified issues -- Assigned responsible persons for bug and feature issues - ---- -*Auto-generated by gitlink-cli community-ops workflow* -"@ +$reportBody = "# $reportTitle" + "`n`n" +$reportBody += "## Summary" + "`n" +$reportBody += "- New Issues: **$newIssuesCount**" + "`n" +$reportBody += "- Closed Issues: **$closedCount**" + "`n" +$reportBody += "- Merged PRs: **$mergedCount**" + "`n`n" +$reportBody += "## Issue Classification" + "`n" +$reportBody += "| Type | Count |" + "`n" +$reportBody += "|------|-------|" + "`n" +$reportBody += "| Bug | $($BugIds.Count) |" + "`n" +$reportBody += "| Feature | $($FeatureIds.Count) |" + "`n" +$reportBody += "| Question | $($QuestionIds.Count) |" + "`n" +$reportBody += "| Docs | $($DocsIds.Count) |" + "`n`n" +$reportBody += "## Highlights" + "`n" +$reportBody += "- Auto-classified and labeled $totalClassified issues" + "`n" +$reportBody += "- Assigned responsible persons for bug and feature issues" + "`n`n" +$reportBody += "---" + "`n" +$reportBody += "*Auto-generated by gitlink-cli community-ops workflow*" Log-Ok "Weekly report generated" Write-Host "" @@ -214,22 +207,23 @@ if ($wikiResult -and (Get-JsonOk ($wikiResult | ConvertFrom-Json))) { Log-Warn "Wiki publish may have failed (wiki module might not be enabled)" } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Phase 4: Auto-Publish Release Notes" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Step "Collecting recent changes for release notes..." $tagName = "weekly-$(Get-Date -Format 'yyyyMMdd')" $releaseName = "Weekly Release $(Get-Date -Format 'yyyy-MM-dd')" -$releaseBody = "# Release Notes - $(Get-Date -Format 'yyyy-MM-dd')`n`n## Merged PRs ($mergedCount)" +$releaseBody = "# Release Notes - $(Get-Date -Format 'yyyy-MM-dd')" + "`n`n" +$releaseBody += "## Merged PRs ($mergedCount)" if ($mergedCount -gt 0) { $limit = [Math]::Min($mergedCount, 10) for ($i = 0; $i -lt $limit; $i++) { - $prTitle = $mergedData[$i].subject ?? $mergedData[$i].title ?? "" - $prNum = $mergedData[$i].id ?? $mergedData[$i].number ?? "" + $prTitle = if ($mergedData[$i].subject) { $mergedData[$i].subject } elseif ($mergedData[$i].title) { $mergedData[$i].title } else { "" } + $prNum = if ($mergedData[$i].id) { $mergedData[$i].id } elseif ($mergedData[$i].number) { $mergedData[$i].number } else { "" } $releaseBody += "`n- #$prNum $prTitle" } } @@ -239,8 +233,8 @@ if ($closedCount -gt 0) { $closedIssues = @($closedJson.data.issues) $limit = [Math]::Min($closedCount, 10) for ($i = 0; $i -lt $limit; $i++) { - $issueTitle = $closedIssues[$i].subject ?? $closedIssues[$i].title ?? "" - $issueNum = $closedIssues[$i].number ?? $closedIssues[$i].id ?? "" + $issueTitle = if ($closedIssues[$i].subject) { $closedIssues[$i].subject } elseif ($closedIssues[$i].title) { $closedIssues[$i].title } else { "" } + $issueNum = if ($closedIssues[$i].number) { $closedIssues[$i].number } elseif ($closedIssues[$i].id) { $closedIssues[$i].id } else { "" } if ($issueTitle) { $releaseBody += "`n- #$issueNum $issueTitle" } } } @@ -255,9 +249,9 @@ if ($releaseResult -and (Get-JsonOk ($releaseResult | ConvertFrom-Json))) { Log-Warn "Release creation may have failed (tag might already exist)" } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Community Operations Complete" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Write-Host " Issues classified: $totalClassified" -ForegroundColor Green Write-Host " Closed this week: $closedCount" -ForegroundColor Green diff --git a/workflows/03-project-init.ps1 b/workflows/03-project-init.ps1 index f0dbd1aa..327f480a 100644 --- a/workflows/03-project-init.ps1 +++ b/workflows/03-project-init.ps1 @@ -1,16 +1,17 @@ -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- # Scenario 3: One-Click Project Initialization -# Flow: Input description → Create repo → README/CONTRIBUTING → CI config → -# Initial Issues + Milestone → Branch protection → Initial Release +# Flow: Input description -> Create repo -> README/CONTRIBUTING/CI config -> +# Initial 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. issue +create -- create initial issues with milestone -# 5. branch +protect -- protect master branch -# 6. release +create -- create initial release -# ───────────────────────────────────────────────────────────────────── +# 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 +# ---------------------------------------------------------------- #Requires -Version 5.1 param( @@ -29,7 +30,7 @@ $ErrorActionPreference = "Stop" Import-Module "$PSScriptRoot/lib/common.psm1" -Force if ($Help) { - Write-Host "Usage: pwsh 03-project-init.ps1 -Owner OWNER -Name REPO_NAME -Description DESC [-Lang go|python|node|java] [-Private] [-DryRun]" + Write-Host "Usage: powershell 03-project-init.ps1 -Owner OWNER -Name REPO_NAME -Description DESC [-Lang go|python|node|java] [-Private] [-DryRun]" exit 0 } @@ -39,9 +40,9 @@ if (-not $Owner) { $Owner = $detected.Owner } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Project Initialization: $Owner/$Name" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Write-Host " Owner: $Owner" Write-Host " Name: $Name" Write-Host " Description: $Description" @@ -49,7 +50,7 @@ Write-Host " Language: $Lang" Write-Host " Private: $($Private.IsPresent)" Divider -# ── Step 1: Create Repository ──────────────────────────────────────── +# -- Step 1: Create Repository -- Log-Step "Creating repository..." $privateStr = if ($Private) { "true" } else { "false" } $repoResult = Invoke-GLCheck repo,+create,--owner,$Owner,--name,$Name,--description,$Description,--private,$privateStr @@ -60,128 +61,34 @@ if ($repoResult) { exit 1 } -# ── Step 2: Create README ──────────────────────────────────────────── +# -- Step 2: Create README -- Log-Step "Creating README wiki page..." Start-Sleep -Seconds 2 -$langContent = switch ($Lang) { +$langSection = switch ($Lang) { "go" { -@" -### Prerequisites -- Go 1.21+ -- Git - -### Installation -``````bash -git clone https://gitlink.org.cn/$Owner/$Name.git -cd $Name -go mod download -go build ./... -`````` - -### Usage -``````bash -go run main.go -`````` - -### Testing -``````bash -go test ./... -`````` -"@ + "### 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 -- Python 3.9+ -- pip - -### Installation -``````bash -git clone https://gitlink.org.cn/$Owner/$Name.git -cd $Name -pip install -r requirements.txt -`````` - -### Usage -``````bash -python main.py -`````` - -### Testing -``````bash -pytest -`````` -"@ + "### 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 -- Node.js 18+ -- npm or yarn - -### Installation -``````bash -git clone https://gitlink.org.cn/$Owner/$Name.git -cd $Name -npm install -`````` - -### Usage -``````bash -npm start -`````` - -### Testing -``````bash -npm test -`````` -"@ + "### 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 -- JDK 17+ -- Maven 3.8+ - -### Installation -``````bash -git clone https://gitlink.org.cn/$Owner/$Name.git -cd $Name -mvn clean install -`````` - -### Usage -``````bash -mvn exec:java -`````` - -### Testing -``````bash -mvn test -`````` -"@ + "### 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 { "" } } -$readmeContent = @" -# $Name - -$Description - -## Getting Started - -$langContent - -## Contributing - -See [CONTRIBUTING](./CONTRIBUTING) for guidelines. - -## License - -This project is licensed under the MIT License. -"@ +$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." $wikiOk = $false for ($attempt = 1; $attempt -le 3; $attempt++) { @@ -195,41 +102,28 @@ for ($attempt = 1; $attempt -le 3; $attempt++) { } if (-not $wikiOk) { Log-Warn "README wiki creation may have failed" } -# ── Step 3: Create CONTRIBUTING Guide ──────────────────────────────── +# -- Step 3: Create CONTRIBUTING Guide -- Log-Step "Creating CONTRIBUTING guide..." -$contribContent = @" -# 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 -- Add tests for new features -- Update documentation as needed - -## Reporting Issues - -- Use the issue tracker -- Include reproduction steps -- Include environment details - -## Code of Conduct - -Please be respectful and constructive in all interactions. -"@ +$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" $wikiOk = $false for ($attempt = 1; $attempt -le 3; $attempt++) { @@ -243,88 +137,50 @@ for ($attempt = 1; $attempt -le 3; $attempt++) { } if (-not $wikiOk) { Log-Warn "CONTRIBUTING wiki creation may have failed" } -# ── Step 4: Create CI Config Wiki Page ─────────────────────────────── +# -- Step 4: Create CI Config Guide -- Log-Step "Creating CI/CD configuration guide..." -$ciContent = @" -# CI/CD Configuration - -## GitLink CI Setup - -This project uses GitLink CI for continuous integration. - -### Pipeline Stages - -1. **Test**: Run unit tests -2. **Build**: Build the project -3. **Deploy**: Deploy to staging (master branch only) - -### Configuration - -Create a ``.gitlink-ci.yml`` file in the repository root: - -``````yaml -stages: - - test - - build - - deploy - -test: - stage: test - script: - - echo "Running tests..." - -build: - stage: build - script: - - echo "Building project..." - -deploy: - stage: deploy - script: - - echo "Deploying..." - only: - - master -`````` - -### Status Badges - -Add a CI status badge to your README: - -``````markdown -[](https://gitlink.org.cn/$Owner/$Name/pipelines) -`````` -"@ +$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." Invoke-GL wiki,+create,--owner,$Owner,--repo,$Name,--title,"CI/CD Configuration",--body,$ciContent | Out-Null Log-Ok "CI/CD configuration guide created" -# ── Step 5: Create Initial Issues with Milestone ───────────────────── +# -- Step 5: Create Initial Issues -- Log-Step "Creating initial issues..." $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 = "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% code coverage`n- [ ] Add CI test integration"; 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" } ) foreach ($entry in $issuesToCreate) { $issueResult = Invoke-GL issue,+create,--owner,$Owner,--repo,$Name,--title,$entry.Title,--body,$entry.Body if ($issueResult) { - $issueJson = $issueResult | ConvertFrom-Json - $issueNum = $issueJson.data.id ?? $issueJson.data.number - if ($issueNum) { - Invoke-GL issue,+label-add,--owner,$Owner,--repo,$Name,--number,$issueNum,--labels,$entry.Label | Out-Null - Log-Ok "Issue created: #$issueNum - $($entry.Title)" + try { + $issueJson = $issueResult | ConvertFrom-Json + $issueNum = if ($issueJson.data.id) { $issueJson.data.id } elseif ($issueJson.data.number) { $issueJson.data.number } else { $null } + if ($issueNum) { + Invoke-GL issue,+label-add,--owner,$Owner,--repo,$Name,--number,$issueNum,--labels,$entry.Label | Out-Null + Log-Ok "Issue created: #$issueNum - $($entry.Title)" + } + } catch { + Log-Warn "Issue creation may have failed: $($entry.Title)" } - } else { - Log-Warn "Issue creation may have failed: $($entry.Title)" } } -# ── Step 6: Protect Default Branch ─────────────────────────────────── +# -- Step 6: Protect Default Branch -- Log-Step "Protecting master branch..." $protectResult = Invoke-GL branch,+protect,--owner,$Owner,--repo,$Name,--name,master if ($protectResult -and (Get-JsonOk ($protectResult | ConvertFrom-Json))) { @@ -333,28 +189,22 @@ if ($protectResult -and (Get-JsonOk ($protectResult | ConvertFrom-Json))) { Log-Warn "Branch protection may have failed (may require admin permissions)" } -# ── Step 7: Create Initial Release ─────────────────────────────────── +# -- Step 7: Create Initial Release -- Log-Step "Creating initial release v0.1.0..." -$releaseBody = @" -# v0.1.0 - Initial Release - -## What's New -- Project initialized with $Lang template -- README and CONTRIBUTING guides created -- CI/CD configuration guide created -- 5 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* -"@ +$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*" $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))) { @@ -363,9 +213,9 @@ if ($releaseResult -and (Get-JsonOk ($releaseResult | ConvertFrom-Json))) { Log-Warn "Release creation may have failed" } -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Log-Title "Project Initialization Complete" -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- Write-Host " Repository: $Owner/$Name" -ForegroundColor Green Write-Host " README: Wiki page" -ForegroundColor Green diff --git a/workflows/04-multi-repo-collab.ps1 b/workflows/04-multi-repo-collab.ps1 index 633ce62c..9e01e759 100644 --- a/workflows/04-multi-repo-collab.ps1 +++ b/workflows/04-multi-repo-collab.ps1 @@ -1,6 +1,6 @@ -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- # Scenario 4: Multi-Repo Collaboration -# Flow: Cross-repo issue tracking → PR status dashboard → Coordinated release +# Flow: Cross-repo issue tracking -> PR status dashboard -> Coordinated release # # Commands chained: # 1. repo +list -- list all repos in org @@ -9,7 +9,7 @@ # 4. release +list -- check release status across repos # 5. release +create -- coordinated release (optional) # 6. Generate HTML dashboard -# ───────────────────────────────────────────────────────────────────── +# ---------------------------------------------------------------- #Requires -Version 5.1 param( @@ -26,13 +26,13 @@ $ErrorActionPreference = "Stop" Import-Module "$PSScriptRoot/lib/common.psm1" -Force if ($Help) { - Write-Host "Usage: pwsh 04-multi-repo-collab.ps1 -Org ORG [-Repos 'repo1,repo2'] [-Release TAG] [-Output FILE] [-DryRun]" + Write-Host "Usage: powershell 04-multi-repo-collab.ps1 -Org ORG [-Repos 'repo1,repo2'] [-Release TAG] [-Output FILE] [-DryRun]" exit 0 } Check-Auth -# ── Step 1: List Repositories ──────────────────────────────────────── +# -- Step 1: List Repositories -- Log-Title "Multi-Repo Collaboration Dashboard" Log-Step "Fetching repositories for org: $Org..." @@ -46,21 +46,20 @@ elseif ($rd -is [array]) { $allRepos = $rd } Log-Ok "Found $($allRepos.Count) repositories" -# Filter repos if specified $repoList = @() if ($Repos) { $repoList = $Repos -split ',' Log-Info "Filtering to specified repos: $($repoList -join ', ')" } else { foreach ($r in $allRepos) { - $rname = $r.name ?? $r.identifier + $rname = if ($r.name) { $r.name } elseif ($r.identifier) { $r.identifier } else { $null } if ($rname) { $repoList += $rname } } } Log-Ok "Will process $($repoList.Count) repositories" -# ── Step 2-3: Collect Issues and PRs from each repo ────────────────── +# -- Step 2-3: Collect Issues and PRs from each repo -- Log-Title "Collecting Data Across Repos" $totalIssues = 0; $totalOpenIssues = 0; $totalPRs = 0; $totalOpenPRs = 0 @@ -70,15 +69,12 @@ foreach ($repo in $repoList) { Divider Log-Step "Processing $Org/$repo..." - # Open issues $issuesJson = Invoke-GL issue,+list,--owner,$Org,--repo,$repo,--state,open,--limit,50 $openIssues = if ($issuesJson) { @($issuesJson.data.issues).Count } else { 0 } - # Closed issues $closedJson = Invoke-GL issue,+list,--owner,$Org,--repo,$repo,--state,closed,--limit,50 $closedIssues = if ($closedJson) { @($closedJson.data.issues).Count } else { 0 } - # Open PRs $prsJson = Invoke-GL pr,+list,--owner,$Org,--repo,$repo,--state,open,--limit,50 $openPRs = 0 if ($prsJson) { @@ -88,7 +84,6 @@ foreach ($repo in $repoList) { elseif ($pd -is [array]) { $openPRs = $pd.Count } } - # Merged PRs $mergedJson = Invoke-GL pr,+list,--owner,$Org,--repo,$repo,--state,merged,--limit,50 $mergedPRs = 0 if ($mergedJson) { @@ -98,53 +93,28 @@ foreach ($repo in $repoList) { elseif ($md -is [array]) { $mergedPRs = $md.Count } } - # Latest release $releaseJson = Invoke-GL release,+list,--owner,$Org,--repo,$repo,--limit,1 $latestRelease = "none" if ($releaseJson -and $releaseJson.data.releases) { $releases = @($releaseJson.data.releases) if ($releases.Count -gt 0) { - $latestRelease = $releases[0].tag_name ?? $releases[0].name ?? "none" + $latestRelease = if ($releases[0].tag_name) { $releases[0].tag_name } elseif ($releases[0].name) { $releases[0].name } else { "none" } } } Log-Ok "$repo : Issues(open:$openIssues closed:$closedIssues) PRs(open:$openPRs merged:$mergedPRs) Release:$latestRelease" - # Build PR details HTML - $prDetailsHtml = "" - if ($openPRs -gt 0 -and $prsJson) { - $prData = @() - $pd2 = $prsJson.data - if ($pd2.issues) { $prData = @($pd2.issues) } - elseif ($pd2.pulls) { $prData = @($pd2.pulls) } - elseif ($pd2 -is [array]) { $prData = $pd2 } - - $limit = [Math]::Min($prData.Count, 5) - for ($i = 0; $i -lt $limit; $i++) { - $prId = $prData[$i].pull_request_number ?? $prData[$i].number ?? $prData[$i].id ?? "" - $prTitle = $prData[$i].subject ?? $prData[$i].title ?? "" - $prAuthor = $prData[$i].author_login ?? $prData[$i].author.login ?? "unknown" - $prDetailsHtml += "