diff --git a/automation/bulk_sync.php b/automation/bulk_sync.php index 021d9dd..90aeba0 100755 --- a/automation/bulk_sync.php +++ b/automation/bulk_sync.php @@ -379,6 +379,7 @@ class BulkSync extends CLIApp // (e.g. 54 new labels on a fresh repo), reset it so file sync proceeds. if (!$this->dryRun) { $this->ensureRepoLabels($org, $repoName); + $this->ensureReleaseTags($org, $repoName); $this->api->resetCircuitBreaker(); } @@ -958,8 +959,51 @@ class BulkSync extends CLIApp } /** - * Create a tracking issue in the target repository after a successful sync. + * Ensure standard release tags exist on the repository. * + * Creates 'development', 'beta', and 'release-candidate' tags pointing + * to the default branch HEAD if they don't already exist. These tags + * are used by the release workflow to track stability channels. + */ + private function ensureReleaseTags(string $org, string $repo): void + { + $requiredTags = ['development', 'beta', 'release-candidate']; + + try { + $existingTags = $this->api->get("/repos/{$org}/{$repo}/tags", ['limit' => 50]); + } catch (\Exception $e) { + return; // Non-critical + } + + $existingNames = array_column($existingTags, 'name'); + + // Get default branch to point new tags at + try { + $repoInfo = $this->api->get("/repos/{$org}/{$repo}"); + $defaultBranch = $repoInfo['default_branch'] ?? 'main'; + } catch (\Exception $e) { + $defaultBranch = 'main'; + } + + foreach ($requiredTags as $tagName) { + if (in_array($tagName, $existingNames, true)) { + continue; + } + + try { + $this->api->post("/repos/{$org}/{$repo}/tags", [ + 'tag_name' => $tagName, + 'target' => $defaultBranch, + 'message' => "Release channel: {$tagName}", + ]); + $this->log(" 🏷️ Created tag '{$tagName}' on {$repo}", 'INFO'); + } catch (\Exception $e) { + // Non-critical — tag may already exist as a release tag + } + } + } + + /** * Merge main into all open PR branches (except the sync branch itself). * * This ensures feature/development branches stay up to date with the