-
Notifications
You must be signed in to change notification settings - Fork 3
update dev #413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
update dev #413
Changes from all commits
bea0f47
76443e6
2d4ed7f
f263f72
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||||||||||||||||||||||||||
| name: 'Check Issues for Version' | ||||||||||||||||||||||||||||||
| description: 'Check if any open issues exist with a specific version label within a time period' | ||||||||||||||||||||||||||||||
| description: 'Check promotion eligibility: milestone status, release age, and open issues with version label (all stages)' | ||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||
| version: | ||||||||||||||||||||||||||||||
| description: 'Version to check for issues (e.g., 1.4.2-alpha)' | ||||||||||||||||||||||||||||||
|
|
@@ -23,6 +23,30 @@ outputs: | |||||||||||||||||||||||||||||
| issues-list: | ||||||||||||||||||||||||||||||
| description: 'Comma-separated list of issue numbers' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.issues_list }} | ||||||||||||||||||||||||||||||
| release-date: | ||||||||||||||||||||||||||||||
| description: 'Release published date (ISO 8601)' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.release_date }} | ||||||||||||||||||||||||||||||
| release-age-days: | ||||||||||||||||||||||||||||||
| description: 'Number of days since release was published' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.release_age_days }} | ||||||||||||||||||||||||||||||
| release-old-enough: | ||||||||||||||||||||||||||||||
| description: 'Whether release is at least 30 days old' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.release_old_enough }} | ||||||||||||||||||||||||||||||
| last-closed-issue-date: | ||||||||||||||||||||||||||||||
| description: 'Date of last closed issue with this version label (ISO 8601)' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.last_closed_issue_date }} | ||||||||||||||||||||||||||||||
| last-closed-age-days: | ||||||||||||||||||||||||||||||
| description: 'Number of days since last issue was closed' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.last_closed_age_days }} | ||||||||||||||||||||||||||||||
| last-closed-old-enough: | ||||||||||||||||||||||||||||||
| description: 'Whether last closed issue is at least 30 days old' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.last_closed_old_enough }} | ||||||||||||||||||||||||||||||
| can-promote: | ||||||||||||||||||||||||||||||
| description: 'Whether all conditions are met for promotion (milestone clear, release old enough, no recent closed issues)' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.can_promote }} | ||||||||||||||||||||||||||||||
| blocking-reason: | ||||||||||||||||||||||||||||||
| description: 'Reason why promotion is blocked (if can-promote is false)' | ||||||||||||||||||||||||||||||
| value: ${{ steps.check-issues.outputs.blocking_reason }} | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| runs: | ||||||||||||||||||||||||||||||
| using: "composite" | ||||||||||||||||||||||||||||||
|
|
@@ -38,53 +62,180 @@ runs: | |||||||||||||||||||||||||||||
| $daysLookback = [int]"${{ inputs.days-lookback }}" | ||||||||||||||||||||||||||||||
| $repo = "${{ github.repository }}" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Write-Host "Checking for issues with label: $labelName" | ||||||||||||||||||||||||||||||
| Write-Host "Looking back $daysLookback days" | ||||||||||||||||||||||||||||||
| Write-Host "=== Promotion Eligibility Check for $version ===" | ||||||||||||||||||||||||||||||
| Write-Host "" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $headers = @{ | ||||||||||||||||||||||||||||||
| "Authorization" = "Bearer $env:GITHUB_TOKEN" | ||||||||||||||||||||||||||||||
| "Accept" = "application/vnd.github.v3+json" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Calculate cutoff date | ||||||||||||||||||||||||||||||
| $cutoffDate = (Get-Date).AddDays(-$daysLookback).ToString("yyyy-MM-dd") | ||||||||||||||||||||||||||||||
| $repoOwner = $repo.Split('/')[0] | ||||||||||||||||||||||||||||||
| $repoName = $repo.Split('/')[1] | ||||||||||||||||||||||||||||||
| $canPromote = $true | ||||||||||||||||||||||||||||||
| $blockingReasons = @() | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Use Search API with created date filter for accurate "created since" semantics | ||||||||||||||||||||||||||||||
| # This is more accurate than the REST API's 'since' parameter which filters by updated_at | ||||||||||||||||||||||||||||||
| $issues = @() | ||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||
| # CHECK 1: Open issues with version label (any stage) | ||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||
| Write-Host "CHECK 1: Looking for ALL open issues with version label (base + all stages)" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Parse version to get base version (X.Y.Z without stage suffix) | ||||||||||||||||||||||||||||||
| if ($version -match '^(\d+\.\d+\.\d+)') { | ||||||||||||||||||||||||||||||
| $baseVersion = $matches[1] | ||||||||||||||||||||||||||||||
| Write-Host " Base version: $baseVersion" | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| Write-Host " ⚠️ Could not parse base version from '$version'" | ||||||||||||||||||||||||||||||
| $baseVersion = $version | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # Search for all open issues with labels matching the base version (any stage) | ||||||||||||||||||||||||||||||
| # This will match: version: X.Y.Z, version: X.Y.Z-alpha, version: X.Y.Z-beta, etc. | ||||||||||||||||||||||||||||||
| $openIssues = @() | ||||||||||||||||||||||||||||||
| $page = 1 | ||||||||||||||||||||||||||||||
| $perPage = 100 | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| do { | ||||||||||||||||||||||||||||||
| # Search API query: state:open label:"version: X.Y.Z" created:>=YYYY-MM-DD | ||||||||||||||||||||||||||||||
| $query = "state:open label:""$labelName"" created:>=$cutoffDate repo:$repo" | ||||||||||||||||||||||||||||||
| # Search for issues with labels starting with "version: X.Y.Z" | ||||||||||||||||||||||||||||||
| $query = "state:open label:""version: $baseVersion"" repo:$repo" | ||||||||||||||||||||||||||||||
| $uri = "https://api.github.com/search/issues?q=$([Uri]::EscapeDataString($query))&per_page=$perPage&page=$page" | ||||||||||||||||||||||||||||||
|
Comment on lines
+92
to
101
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||
| $response = Invoke-RestMethod -Uri $uri -Headers $headers -Method GET | ||||||||||||||||||||||||||||||
| $issues += $response.items | ||||||||||||||||||||||||||||||
| $openIssues += $response.items | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ($response.items.Count -lt $perPage) { | ||||||||||||||||||||||||||||||
| break | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| $page++ | ||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||
| Write-Error "Failed to fetch issues: $($_.Exception.Message)" | ||||||||||||||||||||||||||||||
| Write-Error "Failed to fetch open issues: $($_.Exception.Message)" | ||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } while ($response.items.Count -eq $perPage) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $issueCount = $issues.Count | ||||||||||||||||||||||||||||||
| $issueNumbers = ($issues | ForEach-Object { $_.number }) -join "," | ||||||||||||||||||||||||||||||
| $openIssueCount = $openIssues.Count | ||||||||||||||||||||||||||||||
| $openIssueNumbers = ($openIssues | ForEach-Object { $_.number }) -join "," | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Write-Host "Found $issueCount open issues with label '$labelName'" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ($issueCount -gt 0) { | ||||||||||||||||||||||||||||||
| Write-Host "Issues: $issueNumbers" | ||||||||||||||||||||||||||||||
| if ($openIssueCount -gt 0) { | ||||||||||||||||||||||||||||||
| Write-Host " ❌ Found $openIssueCount open issue(s): $openIssueNumbers" | ||||||||||||||||||||||||||||||
| Write-Host " (Issues discovered in version $baseVersion line, any stage)" | ||||||||||||||||||||||||||||||
| echo "has_issues=true" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| $canPromote = $false | ||||||||||||||||||||||||||||||
| $blockingReasons += "version_label_has_open_issues" | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| Write-Host " ✅ No open issues with version label (checked all stages)" | ||||||||||||||||||||||||||||||
| echo "has_issues=false" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| echo "issue_count=$issueCount" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "issues_list=$issueNumbers" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "issue_count=$openIssueCount" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "issues_list=$openIssueNumbers" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| Write-Host "" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # (CHECK 2 removed: target milestone check was redundant with CHECK 1. | ||||||||||||||||||||||||||||||
| # Bugs from alpha labeled 'version: 1.4.3-alpha' are caught by CHECK 1. | ||||||||||||||||||||||||||||||
| # Checking the beta milestone also incorrectly blocks on planned features.) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||
| # CHECK 3: Release age (must be >= 30 days old) | ||||||||||||||||||||||||||||||
| # ============================================================ | ||||||||||||||||||||||||||||||
| Write-Host "CHECK 3: Checking release age" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||
| # Get release by tag | ||||||||||||||||||||||||||||||
| $releaseUri = "https://api.github.com/repos/$repo/releases/tags/$version" | ||||||||||||||||||||||||||||||
| $release = Invoke-RestMethod -Uri $releaseUri -Headers $headers -Method GET | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| $publishedAt = [DateTime]::Parse($release.published_at) | ||||||||||||||||||||||||||||||
| $now = Get-Date | ||||||||||||||||||||||||||||||
| $ageDays = ($now - $publishedAt).Days | ||||||||||||||||||||||||||||||
| $releaseOldEnough = $ageDays -ge $daysLookback | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Write-Host " Release published: $($publishedAt.ToString('yyyy-MM-dd'))" | ||||||||||||||||||||||||||||||
| Write-Host " Age: $ageDays days" | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if ($releaseOldEnough) { | ||||||||||||||||||||||||||||||
| Write-Host " ✅ Release is old enough (>= $daysLookback days)" | ||||||||||||||||||||||||||||||
| echo "release_old_enough=true" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| Write-Host " ❌ Release is too recent (< $daysLookback days)" | ||||||||||||||||||||||||||||||
| echo "release_old_enough=false" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| $canPromote = $false | ||||||||||||||||||||||||||||||
| $blockingReasons += "release_too_recent" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| echo "release_date=$($publishedAt.ToString('yyyy-MM-ddTHH:mm:ssZ'))" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "release_age_days=$ageDays" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||
| Write-Warning "Failed to fetch release: $($_.Exception.Message)" | ||||||||||||||||||||||||||||||
| echo "release_date=unknown" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "release_age_days=-1" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
| echo "release_old_enough=unknown" >> $env:GITHUB_OUTPUT | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| echo "release_old_enough=unknown" >> $env:GITHUB_OUTPUT | |
| echo "release_old_enough=unknown" >> $env:GITHUB_OUTPUT | |
| $canPromote = $false | |
| $blockingReasons += "release_check_failed" |
Copilot
AI
Mar 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says the search is “sorted by closed date”, but the query uses sort=updated. An older closed issue that was edited/commented recently can appear first, causing an incorrect last_closed_age_days. To make this accurate, fetch a larger set of closed issues and compute the max closed_at yourself (or use a different endpoint/strategy that avoids relying on updated).
| # Search for closed issues with version label, sorted by closed date (most recent first) | |
| $query = "state:closed label:""$labelName"" repo:$repo" | |
| $closedIssuesUri = "https://api.github.com/search/issues?q=$([Uri]::EscapeDataString($query))&sort=updated&order=desc&per_page=1" | |
| $closedResponse = Invoke-RestMethod -Uri $closedIssuesUri -Headers $headers -Method GET | |
| if ($closedResponse.total_count -gt 0 -and $closedResponse.items.Count -gt 0) { | |
| $lastClosedIssue = $closedResponse.items[0] | |
| # Fetch recent closed issues with version label and compute most recent closed date | |
| $query = "state:closed label:""$labelName"" repo:$repo" | |
| $closedIssuesUri = "https://api.github.com/search/issues?q=$([Uri]::EscapeDataString($query))&sort=updated&order=desc&per_page=100" | |
| $closedResponse = Invoke-RestMethod -Uri $closedIssuesUri -Headers $headers -Method GET | |
| if ($closedResponse.total_count -gt 0 -and $closedResponse.items.Count -gt 0) { | |
| $lastClosedIssue = $closedResponse.items | Sort-Object {[DateTime]::Parse($_.closed_at)} -Descending | Select-Object -First 1 |
Copilot
AI
Mar 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly, if the closed-issues check fails, the action sets last_closed_old_enough=unknown but doesn’t block promotion. That can allow promotion even when eligibility couldn’t be validated. Recommend setting $canPromote = $false and adding a blocking reason (e.g., closed_issue_check_failed) in the catch.
| echo "last_closed_old_enough=unknown" >> $env:GITHUB_OUTPUT | |
| echo "last_closed_old_enough=unknown" >> $env:GITHUB_OUTPUT | |
| # Block promotion if closed-issue eligibility could not be validated | |
| if (-not $blockingReasons) { | |
| $blockingReasons = @() | |
| } | |
| $reason = "closed_issue_check_failed" | |
| $blockingReasons += $reason | |
| $canPromote = $false |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -21,11 +21,14 @@ Triggered manually via `release-1-milestone.yml` when a milestone is ready to re | |||||
|
|
||||||
| ## Promotion Release Flow | ||||||
|
|
||||||
| Automatic stage progression after 30 days with no issues: | ||||||
| Automatic stage progression when ALL conditions are met: | ||||||
|
|
||||||
| 1. Daily cron job checks all prerelease versions (alpha/beta/rc) | ||||||
| 2. If no open issues for 30 days → promotes to next stage | ||||||
| 3. Creates promotion PR (e.g., `1.4.3-alpha` → `1.4.3-beta`) | ||||||
| 2. **Promotion requires ALL three conditions**: | ||||||
| - ✅ **No open issues with version label** (any stage of base version, e.g., `version: 1.4.3-alpha`) | ||||||
|
||||||
| - ✅ **No open issues with version label** (any stage of base version, e.g., `version: 1.4.3-alpha`) | |
| - ✅ **No open issues with base version label** (e.g., `version: 1.4.3`; stage-specific labels like `version: 1.4.3-alpha/beta/rc` are not checked) |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -152,31 +152,36 @@ jobs: | |||
| id: should-promote | ||||
| shell: pwsh | ||||
| run: | | ||||
| $hasIssues = "${{ steps.check-issues.outputs.has-issues }}" -eq "true" | ||||
| $canPromote = "${{ steps.check-issues.outputs.can-promote }}" -eq "true" | ||||
| $forcePromote = "${{ github.event.inputs.force-promote }}" -eq "true" | ||||
| $issueCount = "${{ steps.check-issues.outputs.issue-count }}" | ||||
| $blockingReason = "${{ steps.check-issues.outputs.blocking-reason }}" | ||||
| $version = "${{ matrix.version }}" | ||||
|
|
||||
| Write-Host "Checking promotion for version: $version" | ||||
| Write-Host "Has issues: $hasIssues" | ||||
| Write-Host "Issue count: $issueCount" | ||||
| Write-Host "Force promote: $forcePromote" | ||||
|
|
||||
| # Check if version is old enough (at least 30 days since release) | ||||
| # This is a basic check - in a full implementation you'd query the release date | ||||
| Write-Host "=== Promotion Decision for $version ===" | ||||
| Write-Host "" | ||||
| Write-Host "Validation Results:" | ||||
| Write-Host " • Milestone open issues: ${{ steps.check-issues.outputs.milestone-open-count }}" | ||||
|
||||
| Write-Host " • Milestone open issues: ${{ steps.check-issues.outputs.milestone-open-count }}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The action description claims it checks “milestone status”, but the implementation no longer checks milestones (and no milestone-related outputs are produced). Please update the description to match the current behavior or reintroduce milestone checking/outputs if they’re still required.