Skip to content

Commit 34ed00e

Browse files
CopilotTravisEz13Copilot
authored andcommitted
Add log grouping to build.psm1 for collapsible GitHub Actions logs (PowerShell#26326)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: TravisEz13 <10873629+TravisEz13@users.noreply.github.com> Co-authored-by: Travis Plunk <travis.plunk@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 136e94f commit 34ed00e

12 files changed

Lines changed: 253 additions & 33 deletions

File tree

.github/actions/build/ci/action.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ runs:
55
steps:
66
- name: Capture Environment
77
if: success() || failure()
8-
run: 'Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose'
8+
run: |-
9+
Import-Module .\tools\ci.psm1
10+
Show-Environment
911
shell: pwsh
1012
- name: Set Build Name for Non-PR
1113
if: github.event_name != 'PullRequest'

.github/actions/test/linux-packaging/action.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ runs:
66
steps:
77
- name: Capture Environment
88
if: success() || failure()
9-
run: 'Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose'
9+
run: |-
10+
Import-Module ./tools/ci.psm1
11+
Show-Environment
1012
shell: pwsh
1113

1214
- uses: actions/setup-dotnet@v5

.github/actions/test/nix/action.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ runs:
2121
- name: Capture Environment
2222
if: success() || failure()
2323
run: |-
24-
Import-Module ./build.psm1
25-
Write-LogGroupStart -Title 'Environment'
26-
Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
27-
Write-LogGroupEnd -Title 'Environment'
24+
Import-Module ./tools/ci.psm1
25+
Show-Environment
2826
shell: pwsh
2927

3028
- name: Download Build Artifacts

.github/actions/test/windows/action.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,8 @@ runs:
2121
- name: Capture Environment
2222
if: success() || failure()
2323
run: |-
24-
Import-Module ./build.psm1
25-
Write-LogGroupStart -Title 'Environment'
26-
Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
27-
Write-LogGroupEnd -Title 'Environment'
24+
Import-Module ./tools/ci.psm1
25+
Show-Environment
2826
shell: pwsh
2927

3028
- name: Download Build Artifacts
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
---
2+
applyTo:
3+
- "build.psm1"
4+
- "tools/ci.psm1"
5+
- ".github/**/*.yml"
6+
- ".github/**/*.yaml"
7+
---
8+
9+
# Log Grouping Guidelines for GitHub Actions
10+
11+
## Purpose
12+
13+
Guidelines for using `Write-LogGroupStart` and `Write-LogGroupEnd` to create collapsible log sections in GitHub Actions CI/CD runs.
14+
15+
## Key Principles
16+
17+
### 1. Groups Cannot Be Nested
18+
19+
GitHub Actions does not support nested groups. Only use one level of grouping.
20+
21+
**❌ Don't:**
22+
```powershell
23+
Write-LogGroupStart -Title "Outer Group"
24+
Write-LogGroupStart -Title "Inner Group"
25+
# ... operations ...
26+
Write-LogGroupEnd -Title "Inner Group"
27+
Write-LogGroupEnd -Title "Outer Group"
28+
```
29+
30+
**✅ Do:**
31+
```powershell
32+
Write-LogGroupStart -Title "Operation A"
33+
# ... operations ...
34+
Write-LogGroupEnd -Title "Operation A"
35+
36+
Write-LogGroupStart -Title "Operation B"
37+
# ... operations ...
38+
Write-LogGroupEnd -Title "Operation B"
39+
```
40+
41+
### 2. Groups Should Be Substantial
42+
43+
Only create groups for operations that generate substantial output (5+ lines). Small groups add clutter without benefit.
44+
45+
**❌ Don't:**
46+
```powershell
47+
Write-LogGroupStart -Title "Generate Resource Files"
48+
Write-Log -message "Run ResGen"
49+
Start-ResGen
50+
Write-LogGroupEnd -Title "Generate Resource Files"
51+
```
52+
53+
**✅ Do:**
54+
```powershell
55+
Write-Log -message "Run ResGen (generating C# bindings for resx files)"
56+
Start-ResGen
57+
```
58+
59+
### 3. Groups Should Represent Independent Operations
60+
61+
Each group should be a logically independent operation that users might want to expand/collapse separately.
62+
63+
**✅ Good examples:**
64+
- Install Native Dependencies
65+
- Install .NET SDK
66+
- Build PowerShell
67+
- Restore NuGet Packages
68+
69+
**❌ Bad examples:**
70+
- Individual project restores (too granular)
71+
- Small code generation steps (too small)
72+
- Sub-steps of a larger operation (would require nesting)
73+
74+
### 4. One Group Per Iteration Is Excessive
75+
76+
Avoid putting log groups inside loops where each iteration creates a separate group. This would probably cause nesting.
77+
78+
**❌ Don't:**
79+
```powershell
80+
$projects | ForEach-Object {
81+
Write-LogGroupStart -Title "Restore Project: $_"
82+
dotnet restore $_
83+
Write-LogGroupEnd -Title "Restore Project: $_"
84+
}
85+
```
86+
87+
**✅ Do:**
88+
```powershell
89+
Write-LogGroupStart -Title "Restore All Projects"
90+
$projects | ForEach-Object {
91+
Write-Log -message "Restoring $_"
92+
dotnet restore $_
93+
}
94+
Write-LogGroupEnd -Title "Restore All Projects"
95+
```
96+
97+
## Usage Pattern
98+
99+
```powershell
100+
Write-LogGroupStart -Title "Descriptive Operation Name"
101+
try {
102+
# ... operation code ...
103+
Write-Log -message "Status updates"
104+
}
105+
finally {
106+
# Ensure group is always closed
107+
}
108+
Write-LogGroupEnd -Title "Descriptive Operation Name"
109+
```
110+
111+
## When to Use Log Groups
112+
113+
Use log groups for:
114+
- Major build phases (bootstrap, restore, build, test, package)
115+
- Installation operations (dependencies, SDKs, tools)
116+
- Operations that produce 5+ lines of output
117+
- Operations where users might want to collapse verbose output
118+
119+
Don't use log groups for:
120+
- Single-line operations
121+
- Code that's already inside another group
122+
- Loop iterations with minimal output per iteration
123+
- Diagnostic or debug output that should always be visible
124+
125+
## Examples from build.psm1
126+
127+
### Good Usage
128+
129+
```powershell
130+
function Start-PSBootstrap {
131+
# Multiple independent operations, each with substantial output
132+
Write-LogGroupStart -Title "Install Native Dependencies"
133+
# ... apt-get/yum/brew install commands ...
134+
Write-LogGroupEnd -Title "Install Native Dependencies"
135+
136+
Write-LogGroupStart -Title "Install .NET SDK"
137+
# ... dotnet installation ...
138+
Write-LogGroupEnd -Title "Install .NET SDK"
139+
}
140+
```
141+
142+
### Avoid
143+
144+
```powershell
145+
# Too small - just 2-3 lines
146+
Write-LogGroupStart -Title "Generate Resource Files (ResGen)"
147+
Write-Log -message "Run ResGen"
148+
Start-ResGen
149+
Write-LogGroupEnd -Title "Generate Resource Files (ResGen)"
150+
```
151+
152+
## GitHub Actions Syntax
153+
154+
These functions emit GitHub Actions workflow commands:
155+
- `Write-LogGroupStart``::group::Title`
156+
- `Write-LogGroupEnd``::endgroup::`
157+
158+
In the GitHub Actions UI, this renders as collapsible sections with the specified title.
159+
160+
## Testing
161+
162+
Test log grouping locally:
163+
```powershell
164+
$env:GITHUB_ACTIONS = 'true'
165+
Import-Module ./build.psm1
166+
Write-LogGroupStart -Title "Test"
167+
Write-Log -Message "Content"
168+
Write-LogGroupEnd -Title "Test"
169+
```
170+
171+
Output should show:
172+
```
173+
::group::Test
174+
Content
175+
::endgroup::
176+
```
177+
178+
## References
179+
180+
- [GitHub Actions: Grouping log lines](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#grouping-log-lines)
181+
- `build.psm1`: `Write-LogGroupStart` and `Write-LogGroupEnd` function definitions

.github/workflows/analyze-reusable.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ jobs:
5656
# queries: ./path/to/local/query, your-org/your-repo/queries@main
5757

5858
- run: |
59-
Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
59+
Import-Module .\tools\ci.psm1
60+
Show-Environment
6061
name: Capture Environment
6162
shell: pwsh
6263

.github/workflows/linux-ci.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ jobs:
5353
# Set job outputs to values from filter step
5454
outputs:
5555
source: ${{ steps.filter.outputs.source }}
56+
buildModuleChanged: ${{ steps.filter.outputs.buildModuleChanged }}
5657
packagingChanged: ${{ steps.filter.outputs.packagingChanged }}
5758
steps:
5859
- name: checkout
@@ -70,7 +71,7 @@ jobs:
7071
name: Build PowerShell
7172
runs-on: ubuntu-latest
7273
needs: changes
73-
if: ${{ needs.changes.outputs.source == 'true' }}
74+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
7475
steps:
7576
- name: checkout
7677
uses: actions/checkout@v5
@@ -84,7 +85,7 @@ jobs:
8485
needs:
8586
- ci_build
8687
- changes
87-
if: ${{ needs.changes.outputs.source == 'true' }}
88+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
8889
runs-on: ubuntu-latest
8990
steps:
9091
- name: checkout
@@ -101,7 +102,7 @@ jobs:
101102
needs:
102103
- ci_build
103104
- changes
104-
if: ${{ needs.changes.outputs.source == 'true' }}
105+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
105106
runs-on: ubuntu-latest
106107
steps:
107108
- name: checkout
@@ -118,7 +119,7 @@ jobs:
118119
needs:
119120
- ci_build
120121
- changes
121-
if: ${{ needs.changes.outputs.source == 'true' }}
122+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
122123
runs-on: ubuntu-latest
123124
steps:
124125
- name: checkout
@@ -135,7 +136,7 @@ jobs:
135136
needs:
136137
- ci_build
137138
- changes
138-
if: ${{ needs.changes.outputs.source == 'true' }}
139+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
139140
runs-on: ubuntu-latest
140141
steps:
141142
- name: checkout
@@ -151,7 +152,7 @@ jobs:
151152
name: xUnit Tests
152153
needs:
153154
- changes
154-
if: ${{ needs.changes.outputs.source == 'true' }}
155+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
155156
uses: ./.github/workflows/xunit-tests.yml
156157
with:
157158
runner_os: ubuntu-latest

.github/workflows/macos-ci.yml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ jobs:
5353
# Set job outputs to values from filter step
5454
outputs:
5555
source: ${{ steps.filter.outputs.source }}
56+
buildModuleChanged: ${{ steps.filter.outputs.buildModuleChanged }}
5657
steps:
5758
- name: checkout
5859
uses: actions/checkout@v5
@@ -67,7 +68,7 @@ jobs:
6768
name: Build PowerShell
6869
runs-on: macos-15-large
6970
needs: changes
70-
if: ${{ needs.changes.outputs.source == 'true' }}
71+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
7172
steps:
7273
- name: checkout
7374
uses: actions/checkout@v5
@@ -80,7 +81,7 @@ jobs:
8081
needs:
8182
- ci_build
8283
- changes
83-
if: ${{ needs.changes.outputs.source == 'true' }}
84+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
8485
runs-on: macos-15-large
8586
steps:
8687
- name: checkout
@@ -97,7 +98,7 @@ jobs:
9798
needs:
9899
- ci_build
99100
- changes
100-
if: ${{ needs.changes.outputs.source == 'true' }}
101+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
101102
runs-on: macos-15-large
102103
steps:
103104
- name: checkout
@@ -114,7 +115,7 @@ jobs:
114115
needs:
115116
- ci_build
116117
- changes
117-
if: ${{ needs.changes.outputs.source == 'true' }}
118+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
118119
runs-on: macos-15-large
119120
steps:
120121
- name: checkout
@@ -131,7 +132,7 @@ jobs:
131132
needs:
132133
- ci_build
133134
- changes
134-
if: ${{ needs.changes.outputs.source == 'true' }}
135+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
135136
runs-on: macos-15-large
136137
steps:
137138
- name: checkout
@@ -147,7 +148,7 @@ jobs:
147148
name: xUnit Tests
148149
needs:
149150
- changes
150-
if: ${{ needs.changes.outputs.source == 'true' }}
151+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
151152
uses: ./.github/workflows/xunit-tests.yml
152153
with:
153154
runner_os: macos-15-large
@@ -156,7 +157,7 @@ jobs:
156157
name: macOS packaging and testing
157158
needs:
158159
- changes
159-
if: ${{ needs.changes.outputs.source == 'true' }}
160+
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
160161
runs-on:
161162
- macos-15-large
162163
steps:

0 commit comments

Comments
 (0)