Build Installer #68
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build Installer | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| - 'v*.*.*-staging' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version (e.g., 1.0.0 or 1.0.0-staging)' | |
| required: false | |
| default: '' | |
| staging: | |
| description: 'Staging build (no server upload)' | |
| type: boolean | |
| default: false | |
| env: | |
| PYREVIT_VERSION: "5.3.1.25308" | |
| PYREVIT_URL: "https://github.com/pyrevitlabs/pyRevit/releases/download/v5.3.1.25308%2B1659/pyRevit_5.3.1.25308_signed.exe" | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| shell: pwsh | |
| run: | | |
| if ("${{ github.event.inputs.version }}" -ne "") { | |
| $version = "${{ github.event.inputs.version }}" | |
| } elseif ($env:GITHUB_REF -match "refs/tags/v(.+)") { | |
| $version = $matches[1] | |
| } else { | |
| $version = "0.0.1-dev" | |
| } | |
| echo "VERSION=$version" >> $env:GITHUB_OUTPUT | |
| # Determine if this is a staging build | |
| $isStaging = $false | |
| if ("${{ github.event.inputs.staging }}" -eq "true") { | |
| $isStaging = $true | |
| } elseif ($version -match "-staging$") { | |
| $isStaging = $true | |
| } | |
| echo "IS_STAGING=$isStaging" >> $env:GITHUB_OUTPUT | |
| Write-Host "Version: $version, Staging: $isStaging" | |
| - name: Prepare build directory | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Path "build" -Force | |
| Copy-Item -Path "pyrevit.extension" -Destination "build\CPSK.extension" -Recurse | |
| Copy-Item -Path "installer\scripts\*" -Destination "build\" -Force | |
| # Copy requirements.txt, version.yaml and config.py to root (not extension!) | |
| Copy-Item -Path "requirements.txt" -Destination "build\" -Force | |
| Copy-Item -Path "version.yaml" -Destination "build\" -Force | |
| Copy-Item -Path "config.py" -Destination "build\" -Force | |
| - name: Remove dev tools from build | |
| shell: pwsh | |
| run: | | |
| $libDir = "build\CPSK.extension\lib" | |
| # Remove dev tools not needed in production | |
| $devTools = @("pyrevit_checker.py") | |
| foreach ($tool in $devTools) { | |
| $path = Join-Path $libDir $tool | |
| if (Test-Path $path) { | |
| Remove-Item $path -Force | |
| Write-Host "Removed: $tool (dev tool)" | |
| } | |
| } | |
| Write-Host "Files in lib:" | |
| Get-ChildItem $libDir | ForEach-Object { Write-Host " $($_.Name)" } | |
| - name: Set DEBUG=False in config.py | |
| shell: pwsh | |
| run: | | |
| $configFile = "build\config.py" | |
| $content = Get-Content $configFile -Raw -Encoding UTF8 | |
| $content = $content -replace 'DEBUG\s*=\s*True', 'DEBUG = False' | |
| [System.IO.File]::WriteAllText($configFile, $content, [System.Text.UTF8Encoding]::new($false)) | |
| Write-Host "Set DEBUG = False in config.py" | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Minify Python code | |
| shell: pwsh | |
| run: | | |
| Write-Host "Installing python-minifier..." | |
| pip install python-minifier | |
| $libDir = "build\CPSK.extension\lib" | |
| Write-Host "=== Minifying Python files in $libDir ===" | |
| # Encoding declaration required for IronPython with non-ASCII characters | |
| $encodingDecl = "# -*- coding: utf-8 -*-`n" | |
| # Files to minify (lib modules) | |
| Get-ChildItem "$libDir\*.py" | ForEach-Object { | |
| if ($_.Name -ne "__init__.py") { | |
| $originalSize = $_.Length | |
| Write-Host "Minifying: $($_.Name) ($originalSize bytes)" | |
| # Minify with Python 2 compatible settings (no transforms that could break IronPython) | |
| $tempFile = "$($_.FullName).min" | |
| python -m python_minifier $_.FullName --remove-literal-statements --no-remove-annotations --no-hoist-literals --no-rename-locals --no-convert-posargs-to-args -o $tempFile | |
| if (Test-Path $tempFile) { | |
| # Add encoding declaration back (minifier removes comments) | |
| $content = Get-Content $tempFile -Raw -Encoding UTF8 | |
| $content = $encodingDecl + $content | |
| [System.IO.File]::WriteAllText($_.FullName, $content, [System.Text.UTF8Encoding]::new($false)) | |
| Remove-Item $tempFile -Force | |
| $newSize = (Get-Item $_.FullName).Length | |
| $reduction = [math]::Round((1 - $newSize / $originalSize) * 100) | |
| Write-Host " [OK] $originalSize -> $newSize bytes (-$reduction%)" | |
| } else { | |
| Write-Host " [WARN] Minification failed, keeping original" | |
| } | |
| } | |
| } | |
| Write-Host "=== Minification complete ===" | |
| - name: Install Inno Setup | |
| shell: pwsh | |
| run: | | |
| choco install innosetup -y | |
| - name: Build Installer | |
| shell: pwsh | |
| run: | | |
| $version = "${{ steps.version.outputs.VERSION }}" | |
| $pyrevitVersion = "${{ env.PYREVIT_VERSION }}" | |
| $pyrevitUrl = "${{ env.PYREVIT_URL }}" | |
| & "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" ` | |
| /DMyAppVersion="$version" ` | |
| /DPyRevitVersion="$pyrevitVersion" ` | |
| /DPyRevitUrl="$pyrevitUrl" ` | |
| /O"." ` | |
| "installer\setup.iss" | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: CPSK-Tools-Installer | |
| path: "CPSK_Tools_*.exe" | |
| retention-days: 30 | |
| - name: Generate release notes | |
| if: startsWith(github.ref, 'refs/tags/') | |
| id: release_notes | |
| shell: pwsh | |
| run: | | |
| # Get commits since last tag | |
| $lastTag = git describe --tags --abbrev=0 HEAD^ 2>$null | |
| if ($lastTag) { | |
| $commits = git log --pretty=format:"- %s" "$lastTag..HEAD" --no-merges | Where-Object { $_ -notmatch "Release v" } | |
| $authors = git log --pretty=format:"%an" "$lastTag..HEAD" --no-merges | Sort-Object -Unique | Where-Object { $_ -ne "github-actions[bot]" } | |
| } else { | |
| $commits = git log --pretty=format:"- %s" -10 --no-merges | Where-Object { $_ -notmatch "Release v" } | |
| $authors = git log --pretty=format:"%an" -10 --no-merges | Sort-Object -Unique | Where-Object { $_ -ne "github-actions[bot]" } | |
| } | |
| $version = "${{ steps.version.outputs.VERSION }}" | |
| # Release notes for server (markdown) | |
| $serverNotes = "## CPSK Tools v$version`n`n" | |
| $serverNotes += "### Изменения`n" | |
| if ($commits) { | |
| $serverNotes += ($commits -join "`n") | |
| } else { | |
| $serverNotes += "- Обновление версии" | |
| } | |
| if ($authors) { | |
| $serverNotes += "`n`n### Авторы`n" | |
| $serverNotes += ($authors | ForEach-Object { "- $_" }) -join "`n" | |
| } | |
| $serverNotes += "`n`n### Требования`n- Windows 10/11`n- Autodesk Revit 2021-2025" | |
| $serverNotes | Out-File -FilePath "release_notes.txt" -Encoding UTF8 | |
| # Release notes for GitHub (with install instructions) | |
| $githubNotes = "## CPSK Tools for Revit v$version`n`n" | |
| $githubNotes += "### Установка`n" | |
| $githubNotes += "1. Скачайте ``CPSK_Tools_v$version.exe```n" | |
| $githubNotes += "2. Запустите установщик`n" | |
| $githubNotes += "3. Перезапустите Revit`n`n" | |
| $githubNotes += "### Изменения`n" | |
| if ($commits) { | |
| $githubNotes += ($commits -join "`n") | |
| } else { | |
| $githubNotes += "- Обновление версии" | |
| } | |
| if ($authors) { | |
| $githubNotes += "`n`n### Авторы`n" | |
| $githubNotes += ($authors | ForEach-Object { "- $_" }) -join "`n" | |
| } | |
| $githubNotes += "`n`n### Требования`n- Windows 10/11`n- Autodesk Revit 2021-2025" | |
| $githubNotes | Out-File -FilePath "github_release_notes.txt" -Encoding UTF8 | |
| Write-Host "Release notes generated" | |
| - name: Create Release | |
| if: startsWith(github.ref, 'refs/tags/') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| name: "CPSK Tools v${{ steps.version.outputs.VERSION }}" | |
| body_path: github_release_notes.txt | |
| files: "CPSK_Tools_*.exe" | |
| draft: false | |
| prerelease: ${{ steps.version.outputs.IS_STAGING == 'True' }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Upload to release server | |
| if: startsWith(github.ref, 'refs/tags/') && steps.version.outputs.IS_STAGING != 'True' | |
| shell: pwsh | |
| run: | | |
| $version = "${{ steps.version.outputs.VERSION }}" | |
| $token = "${{ secrets.RELEASE_API_TOKEN }}" | |
| if (-not $token) { | |
| Write-Host "WARNING: RELEASE_API_TOKEN secret not set, skipping upload" | |
| exit 0 | |
| } | |
| $exeFile = Get-ChildItem -Path "." -Filter "CPSK_Tools_*.exe" | Select-Object -First 1 | |
| if (-not $exeFile) { | |
| Write-Host "ERROR: No exe file found" | |
| exit 1 | |
| } | |
| # Read release notes from file | |
| $releaseNotes = Get-Content -Path "release_notes.txt" -Raw -Encoding UTF8 | |
| Write-Host "Uploading $($exeFile.Name) to release server..." | |
| $headers = @{ | |
| "Authorization" = "Bearer $token" | |
| } | |
| $form = @{ | |
| version = $version | |
| exe_file = Get-Item $exeFile.FullName | |
| release_notes = $releaseNotes | |
| git_tag = "v$version" | |
| git_commit = "${{ github.sha }}" | |
| github_release_url = "https://github.com/${{ github.repository }}/releases/tag/v$version" | |
| min_revit_version = "2021" | |
| max_revit_version = "2025" | |
| } | |
| try { | |
| $response = Invoke-RestMethod -Uri "https://rocket-tools.ru/api/rocketrevit/releases/upload/" ` | |
| -Method POST ` | |
| -Headers $headers ` | |
| -Form $form | |
| Write-Host "Upload successful!" | |
| Write-Host "Response: $($response | ConvertTo-Json)" | |
| } catch { | |
| Write-Host "ERROR: Upload failed: $_" | |
| Write-Host "Response: $($_.ErrorDetails.Message)" | |
| # Don't fail the build if upload fails - GitHub release is already created | |
| Write-Host "WARNING: Server upload failed, but GitHub release was created successfully" | |
| } |