Skip to content

APIGenerator CI/CD Pipeline #32

APIGenerator CI/CD Pipeline

APIGenerator CI/CD Pipeline #32

Workflow file for this run

name: APIGenerator CI/CD Pipeline
on:
workflow_dispatch:
schedule:
- cron: '0 1 * * 0' # Every Sunday at 1 AM UTC
permissions:
contents: write
pull-requests: write
env:
TARGET_BRANCH: automatic-api-updates
# This branch is used for automatic API updates
FALLBACK_BRANCH: main
jobs:
run:
if: github.ref == 'refs/heads/main'
runs-on: windows-latest
steps:
- name: Resolve branch to use
id: resolve_branch
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TARGET_BRANCH: ${{ env.TARGET_BRANCH }}
FALLBACK_BRANCH: ${{ env.FALLBACK_BRANCH }}
run: |
$REPO = "github.com/$env:GITHUB_REPOSITORY"
$targetBranchExists = git ls-remote --heads "https://x-access-token:$env:GITHUB_TOKEN@$REPO" $env:TARGET_BRANCH
if ($targetBranchExists) {
"branch=$env:TARGET_BRANCH" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
} else {
"branch=$env:FALLBACK_BRANCH" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
}
- name: Checkout main repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ steps.resolve_branch.outputs.branch }}
fetch-depth: 0
- name: Show which branch was used
run: "echo \"Using branch: ${{ steps.resolve_branch.outputs.branch }}\""
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- name: Setup NuGet.exe for use with actions
uses: NuGet/[email protected]
- name: Create Repositories directory
run: mkdir Repositories
- name: Read and clone repositories
run: |
# Check if repos file exists
if (!(Test-Path "APIGenerator\APIGenerator\Repos.txt")) {
Write-Error "Error: Repos.txt not found at APIGenerator\APIGenerator\Repos.txt"
exit 1
}
# Read repos and clone them
Get-Content "APIGenerator\APIGenerator\Repos.txt" | ForEach-Object {
$repo_url = $_.Trim()
# Skip empty lines and comments
if ([string]::IsNullOrWhiteSpace($repo_url) -or $repo_url.StartsWith("#")) {
return
}
# Extract repo name from URL
$repo_name = [System.IO.Path]::GetFileNameWithoutExtension($repo_url)
if ($repo_name.EndsWith(".git")) {
$repo_name = $repo_name.Substring(0, $repo_name.Length - 4)
}
Write-Host "Processing repository: $repo_name"
# Clone repository
try {
git clone $repo_url "Repositories\$repo_name"
Write-Host "Successfully cloned $repo_name"
# Check if .sln file exists in base folder
$sln_files = Get-ChildItem "Repositories\$repo_name" -Filter "*.sln" -File
if ($sln_files.Count -gt 0) {
Write-Host "✓ Found .sln file in $repo_name - keeping repository"
$repo_name | Add-Content "valid_repos.txt" -Encoding UTF8
} else {
Write-Host "✗ No .sln file found in base folder of $repo_name - Repo not built"
}
} catch {
Write-Host "Failed to clone $repo_name"
}
}
# Show summary
if (Test-Path "valid_repos.txt") {
Write-Host "Valid repositories to compile:"
Get-Content "valid_repos.txt"
} else {
Write-Host "No valid repositories found with .sln files"
}
shell: pwsh
- name: Compile repositories in order
run: |
if (!(Test-Path "valid_repos.txt")) {
Write-Host "No valid repositories to compile"
exit 0
}
# Compile each valid repository
Get-Content "valid_repos.txt" | ForEach-Object {
$repo_name = $_.Trim()
Write-Host "Compiling repository: $repo_name"
Push-Location "Repositories\$repo_name"
try {
# Find and restore packages for all .sln files
Get-ChildItem -Filter "*.sln" -File | ForEach-Object {
Write-Host "Restoring packages for $($_.Name)"
dotnet restore $_.Name 2>&1 | Tee-Object -Variable restoreOutput
Write-Host $restoreOutput
}
# Build all .sln files in the repository
Get-ChildItem -Filter "*.sln" -File | ForEach-Object {
Write-Host "Building $($_.Name) with dotnet build"
dotnet build $_.Name --configuration Release --no-restore 2>&1 | Tee-Object -Variable buildOutput
Write-Host $buildOutput
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Successfully built $($_.Name) with dotnet build"
} else {
Write-Host "✗ dotnet build failed for $($_.Name), trying MSBuild..." -ForegroundColor Yellow
Write-Host "dotnet build errors:" -ForegroundColor Red
Write-Host $buildOutput -ForegroundColor Red
# Restore packages with MSBuild/NuGet
Write-Host "Restoring packages with MSBuild..."
nuget restore $_.Name
# Try with MSBuild as fallback
msbuild $_.Name /p:Configuration=Release /p:Platform="Any CPU" /m 2>&1 | Tee-Object -Variable msbuildOutput
Write-Host $msbuildOutput
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Successfully built $($_.Name) with MSBuild"
} else {
Write-Host "✗ Both dotnet build and MSBuild failed for $($_.Name)" -ForegroundColor Red
Write-Host "MSBuild errors:" -ForegroundColor Red
Write-Host $msbuildOutput -ForegroundColor Red
exit 1
}
}
}
} finally {
Pop-Location
}
}
shell: pwsh
- name: Clean docs/oM folder
run: |
$docsPath = "docs\oM"
if (Test-Path $docsPath) {
Write-Host "Found docs/oM folder, removing all subfolders and their content..."
# Get all subdirectories in docs/oM
$subfolders = Get-ChildItem -Path $docsPath -Directory
if ($subfolders.Count -gt 0) {
foreach ($folder in $subfolders) {
Write-Host "Removing subfolder: $($folder.Name)"
Remove-Item -Path $folder.FullName -Recurse -Force
}
Write-Host "✓ Successfully removed $($subfolders.Count) subfolders from docs/oM"
} else {
Write-Host "No subfolders found in docs/oM"
}
} else {
Write-Host "docs/oM folder not found, skipping cleanup"
}
shell: pwsh
- name: Compile APIGenerator solution
run: |
Write-Host "Compiling APIGenerator.sln"
# Check if the solution file exists
if (!(Test-Path "APIGenerator\APIGenerator.sln")) {
Write-Error "Error: APIGenerator.sln not found at APIGenerator\APIGenerator.sln"
exit 1
}
# Restore packages
Write-Host "Restoring packages for APIGenerator.sln"
dotnet restore "APIGenerator\APIGenerator.sln" 2>&1 | Tee-Object -Variable restoreOutput
Write-Host $restoreOutput
# Build the solution
Write-Host "Building APIGenerator.sln with dotnet build"
dotnet build "APIGenerator\APIGenerator.sln" --configuration Release --no-restore 2>&1 | Tee-Object -Variable buildOutput
Write-Host $buildOutput
if ($LASTEXITCODE -ne 0) {
Write-Host "dotnet build failed, trying MSBuild..." -ForegroundColor Yellow
Write-Host "dotnet build errors:" -ForegroundColor Red
Write-Host $buildOutput -ForegroundColor Red
# Restore packages with MSBuild
Write-Host "Restoring packages with MSBuild..."
msbuild "APIGenerator\APIGenerator.sln" -t:Restore /p:Configuration=Release 2>&1 | Tee-Object -Variable msbuildRestoreOutput
Write-Host $msbuildRestoreOutput
msbuild "APIGenerator\APIGenerator.sln" /p:Configuration=Release /p:Platform="Any CPU" /m 2>&1 | Tee-Object -Variable msbuildOutput
Write-Host $msbuildOutput
if ($LASTEXITCODE -ne 0) {
Write-Host "Both dotnet build and MSBuild failed for APIGenerator.sln" -ForegroundColor Red
Write-Host "MSBuild errors:" -ForegroundColor Red
Write-Host $msbuildOutput -ForegroundColor Red
exit 1
} else {
Write-Host "✓ Successfully built APIGenerator.sln with MSBuild"
}
} else {
Write-Host "✓ Successfully built APIGenerator.sln with dotnet build"
}
shell: pwsh
- name: Find and run APIGenerator executable
run: |
Write-Host "Looking for APIGenerator executable..."
# Look for the executable in common build output locations
$possible_paths = @(
"APIGenerator\APIGenerator\bin\Release\net*\APIGenerator.exe",
"APIGenerator\bin\Release\net*\APIGenerator.exe"
)
$exe_path = $null
foreach ($pattern in $possible_paths) {
$found_files = Get-ChildItem -Path $pattern -ErrorAction SilentlyContinue
if ($found_files) {
$exe_path = $found_files[0].FullName
break
}
}
# If no .exe found, try using dotnet run
if ([string]::IsNullOrEmpty($exe_path)) {
Write-Host "No executable found, trying dotnet run..."
if (Test-Path "APIGenerator\APIGenerator.csproj") {
Push-Location "APIGenerator"
dotnet run --project APIGenerator.csproj --configuration Release
Pop-Location
} elseif (Test-Path "APIGenerator\APIGenerator\APIGenerator.csproj") {
Push-Location "APIGenerator"
dotnet run --project APIGenerator\APIGenerator.csproj --configuration Release
Pop-Location
} else {
Write-Error "Could not find APIGenerator.csproj file"
exit 1
}
} else {
Write-Host "Found executable at: $exe_path"
Write-Host "Running APIGenerator..."
# Run the executable
& $exe_path
}
shell: pwsh
- name: Commit and push changes
run: |
# Configure git
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Create and checkout new branch (or switch if exists)
$branch_name = "${{ env.TARGET_BRANCH }}"
git checkout $branch_name 2>$null || git checkout -b $branch_name
# Add all changes (including new files and directories)
git add -A
# Check if there are any changes to commit
$changes = git status --porcelain
if ($changes) {
Write-Host "Changes detected, committing..."
git commit -m "APIGenerator workflow results - $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
# Push the branch
git push origin $branch_name
Write-Host "Successfully pushed changes to branch: $branch_name"
# Check if a PR already exists for this branch
$existingPr = gh pr list --head $branch_name --base main --json number --jq '.[0].number'
if ($existingPr) {
Write-Host "PR already exists (#$existingPr), adding a comment..."
gh pr comment $existingPr --body "Automated API documentation updates pushed to branch '$branch_name' on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')."
Write-Host "✓ Comment added to existing PR"
} else {
Write-Host "Creating pull request..."
gh pr create --title "API Updates" --body "Automated API documentation updates generated by APIGenerator workflow on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" --head $branch_name --base main
Write-Host "✓ Pull request created successfully"
}
} else {
Write-Host "No changes to commit"
}
shell: pwsh
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}