diff --git a/.github/actions/infrastructure/path-filters/action.yml b/.github/actions/infrastructure/path-filters/action.yml index 09ed7c22d17..ff07c4510fc 100644 --- a/.github/actions/infrastructure/path-filters/action.yml +++ b/.github/actions/infrastructure/path-filters/action.yml @@ -88,12 +88,14 @@ runs: const globalConfigChanged = files.some(file => file.filename.startsWith('.globalconfig')) || files.some(file => file.filename.startsWith('nuget.config')) || files.some(file => file.filename.startsWith('global.json')); - const packagingChanged = files.some(file => + const packagingChanged = files.some(file => file.filename === '.github/workflows/windows-ci.yml' || + file.filename === '.github/workflows/linux-ci.yml' || file.filename.startsWith('assets/wix/') || file.filename === 'PowerShell.Common.props' || file.filename.match(/^src\/.*\.csproj$/) || file.filename.startsWith('test/packaging/windows/') || + file.filename.startsWith('test/packaging/linux/') || file.filename.startsWith('tools/packaging/') || file.filename.startsWith('tools/wix/') ) || @@ -112,7 +114,7 @@ runs: core.setOutput('globalConfigChanged', globalConfigChanged); core.setOutput('packagingChanged', packagingChanged); core.setOutput('source', source); - + - name: Capture outputs run: | diff --git a/.github/actions/test/linux-packaging/action.yml b/.github/actions/test/linux-packaging/action.yml index b7bbdf37185..374205f2a56 100644 --- a/.github/actions/test/linux-packaging/action.yml +++ b/.github/actions/test/linux-packaging/action.yml @@ -13,68 +13,19 @@ runs: with: global-json-file: ./global.json - - name: Download Build Artifacts - uses: actions/download-artifact@v4 - with: - name: build - path: "${{ runner.workspace }}/build" - - - name: Capture Artifacts Directory - continue-on-error: true - run: Get-ChildItem "${{ runner.workspace }}/build/*" -Recurse - shell: pwsh - - name: Bootstrap run: |- Import-Module ./build.psm1 Start-PSBootstrap -Scenario Package - Write-Verbose -Verbose "Start Sync-PSTags" - Sync-PSTags -AddRemoteIfMissing - Write-Verbose -Verbose "End Sync-PSTags" - shell: pwsh - - - name: Extract Build ZIP - run: |- - $destinationFolder = "${{ runner.workspace }}/bins" - $archiveFile = "${{ runner.workspace }}/build/build.zip" - - Write-Verbose "Extracting $archiveFile to $destinationFolder" -Verbose - New-Item -ItemType Directory -Path $destinationFolder -Force | Out-Null - Expand-Archive -Path $archiveFile -DestinationPath $destinationFolder -Force - shell: pwsh - - - name: Fix permissions - continue-on-error: true - run: |- - find "${{ runner.workspace }}/bins" -type d -exec chmod +rwx {} \; - find "${{ runner.workspace }}/bins" -type f -exec chmod +rw {} \; - shell: bash - - - name: Capture Extracted Build ZIP - continue-on-error: true - run: Get-ChildItem "${{ runner.workspace }}/bins/*" -Recurse -ErrorAction SilentlyContinue + Import-Module ./tools/ci.psm1 + Invoke-CIInstall -SkipUser shell: pwsh - - name: Create Packages - env: - BUILD_ARTIFACTSTAGINGDIRECTORY: ${{ runner.workspace }}/packages + - name: Build and Package run: |- - # Create the artifacts staging directory - New-Item -ItemType Directory -Path "$env:BUILD_ARTIFACTSTAGINGDIRECTORY" -Force | Out-Null - - # Import packaging module to ensure RPM packaging changes are loaded - Import-Module ./build.psm1 -Force - Import-Module ./tools/packaging/packaging.psm1 -Force Import-Module ./tools/ci.psm1 - Restore-PSOptions -PSOptionsPath '${{ runner.workspace }}/build/psoptions.json' - $options = (Get-PSOptions) - $rootPath = '${{ runner.workspace }}/bins' - $originalRootPath = Split-Path -path $options.Output - $path = Join-Path -path $rootPath -ChildPath (split-path -leaf -path $originalRootPath) - $pwshPath = Join-Path -path $path -ChildPath 'pwsh' - chmod a+x $pwshPath - $options.Output = $pwshPath - Set-PSOptions $options + $releaseTag = Get-ReleaseTag + Start-PSBuild -Configuration 'Release' -ReleaseTag $releaseTag Invoke-CIFinish shell: pwsh diff --git a/.github/instructions/build-and-packaging-steps.instructions.md b/.github/instructions/build-and-packaging-steps.instructions.md new file mode 100644 index 00000000000..934b1539593 --- /dev/null +++ b/.github/instructions/build-and-packaging-steps.instructions.md @@ -0,0 +1,127 @@ +--- +applyTo: + - ".github/actions/**/*.yml" + - ".github/workflows/**/*.yml" +--- + +# Build and Packaging Steps Pattern + +## Important Rule + +**Build and packaging must run in the same step OR you must save and restore PSOptions between steps.** + +## Why This Matters + +When `Start-PSBuild` runs, it creates PSOptions that contain build configuration details (runtime, configuration, output path, etc.). The packaging functions like `Start-PSPackage` and `Invoke-CIFinish` rely on these PSOptions to know where the build output is located and how it was built. + +GitHub Actions steps run in separate PowerShell sessions. This means PSOptions from one step are not available in the next step. + +## Pattern 1: Combined Build and Package (Recommended) + +Run build and packaging in the same step to keep PSOptions in memory: + +```yaml +- name: Build and Package + run: |- + Import-Module ./tools/ci.psm1 + $releaseTag = Get-ReleaseTag + Start-PSBuild -Configuration 'Release' -ReleaseTag $releaseTag + Invoke-CIFinish + shell: pwsh +``` + +**Benefits:** +- Simpler code +- No need for intermediate files +- PSOptions automatically available to packaging + +## Pattern 2: Separate Steps with Save/Restore + +If you must separate build and packaging into different steps: + +```yaml +- name: Build PowerShell + run: |- + Import-Module ./tools/ci.psm1 + $releaseTag = Get-ReleaseTag + Start-PSBuild -Configuration 'Release' -ReleaseTag $releaseTag + Save-PSOptions -PSOptionsPath "${{ runner.workspace }}/psoptions.json" + shell: pwsh + +- name: Create Packages + run: |- + Import-Module ./tools/ci.psm1 + Restore-PSOptions -PSOptionsPath "${{ runner.workspace }}/psoptions.json" + Invoke-CIFinish + shell: pwsh +``` + +**When to use:** +- When you need to run other steps between build and packaging +- When build and packaging require different permissions or environments + +## Common Mistakes + +### ❌ Incorrect: Separate steps without save/restore + +```yaml +- name: Build PowerShell + run: |- + Start-PSBuild -Configuration 'Release' + shell: pwsh + +- name: Create Packages + run: |- + Invoke-CIFinish # ❌ FAILS: PSOptions not available + shell: pwsh +``` + +### ❌ Incorrect: Using artifacts without PSOptions + +```yaml +- name: Download Build Artifacts + uses: actions/download-artifact@v4 + with: + name: build + +- name: Create Packages + run: |- + Invoke-CIFinish # ❌ FAILS: PSOptions not restored + shell: pwsh +``` + +## Related Functions + +- `Start-PSBuild` - Builds PowerShell and sets PSOptions +- `Save-PSOptions` - Saves PSOptions to a JSON file +- `Restore-PSOptions` - Loads PSOptions from a JSON file +- `Get-PSOptions` - Gets current PSOptions +- `Set-PSOptions` - Sets PSOptions +- `Start-PSPackage` - Creates packages (requires PSOptions) +- `Invoke-CIFinish` - Calls packaging (requires PSOptions on Linux/macOS) + +## Examples + +### Linux Packaging Action + +```yaml +- name: Build and Package + run: |- + Import-Module ./tools/ci.psm1 + $releaseTag = Get-ReleaseTag + Start-PSBuild -Configuration 'Release' -ReleaseTag $releaseTag + Invoke-CIFinish + shell: pwsh +``` + +### Windows Packaging Workflow + +```yaml +- name: Build and Package + run: | + Import-Module .\tools\ci.psm1 + Invoke-CIFinish -Runtime ${{ matrix.runtimePrefix }}-${{ matrix.architecture }} -channel ${{ matrix.channel }} + shell: pwsh +``` + +Note: `Invoke-CIFinish` for Windows includes both build and packaging in its logic when `Stage` contains 'Build'. diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml index a2a8fc4c79e..55cf112ea43 100644 --- a/.github/workflows/linux-ci.yml +++ b/.github/workflows/linux-ci.yml @@ -233,7 +233,6 @@ jobs: linux_packaging: name: Linux Packaging needs: - - ci_build - changes if: ${{ needs.changes.outputs.packagingChanged == 'true' }} runs-on: ubuntu-latest