Skip to content

Commit a643dc4

Browse files
CopilotpwshBot
authored andcommitted
Cherry-pick PR PowerShell#26350 with conflicts for manual resolution
1 parent a9bc941 commit a643dc4

File tree

10 files changed

+1084
-62
lines changed

10 files changed

+1084
-62
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Merge Conflict Checker
2+
3+
This composite GitHub Action checks for Git merge conflict markers in files changed in pull requests.
4+
5+
## Purpose
6+
7+
Automatically detects leftover merge conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) in pull request files to prevent them from being merged into the codebase.
8+
9+
## Usage
10+
11+
### In a Workflow
12+
13+
```yaml
14+
- name: Check for merge conflict markers
15+
uses: "./.github/actions/infrastructure/merge-conflict-checker"
16+
```
17+
18+
### Complete Example
19+
20+
```yaml
21+
jobs:
22+
merge_conflict_check:
23+
name: Check for Merge Conflict Markers
24+
runs-on: ubuntu-latest
25+
if: github.event_name == 'pull_request'
26+
permissions:
27+
pull-requests: read
28+
contents: read
29+
steps:
30+
- name: checkout
31+
uses: actions/checkout@v5
32+
33+
- name: Check for merge conflict markers
34+
uses: "./.github/actions/infrastructure/merge-conflict-checker"
35+
```
36+
37+
## How It Works
38+
39+
1. **File Detection**: Uses GitHub's API to get the list of files changed in the pull request
40+
2. **Marker Scanning**: Reads each changed file and searches for the following markers:
41+
- `<<<<<<<` (conflict start marker)
42+
- `=======` (conflict separator)
43+
- `>>>>>>>` (conflict end marker)
44+
3. **Result Reporting**:
45+
- If markers are found, the action fails and lists all affected files
46+
- If no markers are found, the action succeeds
47+
48+
## Outputs
49+
50+
- `files-checked`: Number of files that were checked
51+
- `conflicts-found`: Number of files containing merge conflict markers
52+
53+
## Behavior
54+
55+
- **Event Support**: Only works with `pull_request` events
56+
- **File Handling**:
57+
- Checks only files that were added, modified, or renamed
58+
- Skips deleted files
59+
- Skips binary/unreadable files
60+
- Skips directories
61+
62+
## Example Output
63+
64+
When conflict markers are detected:
65+
66+
```
67+
❌ Merge conflict markers detected in the following files:
68+
- src/example.cs
69+
Markers found: <<<<<<<, =======, >>>>>>>
70+
- README.md
71+
Markers found: <<<<<<<, =======, >>>>>>>
72+
73+
Please resolve these conflicts before merging.
74+
```
75+
76+
When no markers are found:
77+
78+
```
79+
✅ No merge conflict markers found
80+
```
81+
82+
## Integration
83+
84+
This action is integrated into the `linux-ci.yml` workflow and runs automatically on all pull requests to ensure code quality before merging.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: 'Check for Merge Conflict Markers'
2+
description: 'Checks for Git merge conflict markers in changed files for pull requests'
3+
author: 'PowerShell Team'
4+
5+
outputs:
6+
files-checked:
7+
description: 'Number of files checked for merge conflict markers'
8+
value: ${{ steps.check.outputs.files-checked }}
9+
conflicts-found:
10+
description: 'Number of files with merge conflict markers'
11+
value: ${{ steps.check.outputs.conflicts-found }}
12+
13+
runs:
14+
using: 'composite'
15+
steps:
16+
- name: Get changed files
17+
id: changed-files
18+
uses: "./.github/actions/infrastructure/get-changed-files"
19+
20+
- name: Check for merge conflict markers
21+
id: check
22+
shell: pwsh
23+
env:
24+
CHANGED_FILES_JSON: ${{ steps.changed-files.outputs.files }}
25+
run: |
26+
# Get changed files from environment variable (secure against injection)
27+
$changedFilesJson = $env:CHANGED_FILES_JSON
28+
$changedFiles = $changedFilesJson | ConvertFrom-Json
29+
30+
# Import ci.psm1 and run the check
31+
Import-Module "$env:GITHUB_WORKSPACE/tools/ci.psm1" -Force
32+
Test-MergeConflictMarker -File $changedFiles -WorkspacePath $env:GITHUB_WORKSPACE
33+
34+
branding:
35+
icon: 'alert-triangle'
36+
color: 'red'

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,25 @@ runs:
7575
Invoke-CIFinish
7676
shell: pwsh
7777

78+
<<<<<<< HEAD
79+
=======
80+
- name: Install Pester
81+
run: |-
82+
Import-Module ./tools/ci.psm1
83+
Install-CIPester
84+
shell: pwsh
85+
86+
- name: Validate Package Names
87+
run: |-
88+
# Run Pester tests to validate package names
89+
Import-Module Pester -Force
90+
$testResults = Invoke-Pester -Path ./test/packaging/linux/package-validation.tests.ps1 -PassThru
91+
if ($testResults.FailedCount -gt 0) {
92+
throw "Package validation tests failed"
93+
}
94+
shell: pwsh
95+
96+
>>>>>>> 0c40a84ab (Add merge conflict marker detection to linux-ci workflow and refactor existing actions to use reusable get-changed-files action (#26350))
7897
- name: Upload deb packages
7998
uses: actions/upload-artifact@v4
8099
with:
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
applyTo:
3+
- "**/*.ps1"
4+
- "**/*.psm1"
5+
---
6+
7+
# PowerShell Automatic Variables - Naming Guidelines
8+
9+
## Purpose
10+
11+
This instruction provides guidelines for avoiding conflicts with PowerShell's automatic variables when writing PowerShell scripts and modules.
12+
13+
## What Are Automatic Variables?
14+
15+
PowerShell has built-in automatic variables that are created and maintained by PowerShell itself. Assigning values to these variables can cause unexpected behavior and side effects.
16+
17+
## Common Automatic Variables to Avoid
18+
19+
### Critical Variables (Never Use)
20+
21+
- **`$matches`** - Contains the results of regular expression matches. Overwriting this can break regex operations.
22+
- **`$_`** - Represents the current object in the pipeline. Only use within pipeline blocks.
23+
- **`$PSItem`** - Alias for `$_`. Same rules apply.
24+
- **`$args`** - Contains an array of undeclared parameters. Don't use as a regular variable.
25+
- **`$input`** - Contains an enumerator of all input passed to a function. Don't reassign.
26+
- **`$LastExitCode`** - Exit code of the last native command. Don't overwrite unless intentional.
27+
- **`$?`** - Success status of the last command. Don't use as a variable name.
28+
- **`$$`** - Last token in the last line received by the session. Don't use.
29+
- **`$^`** - First token in the last line received by the session. Don't use.
30+
31+
### Context Variables (Use with Caution)
32+
33+
- **`$Error`** - Array of error objects. Don't replace, but can modify (e.g., `$Error.Clear()`).
34+
- **`$PSBoundParameters`** - Parameters passed to the current function. Read-only.
35+
- **`$MyInvocation`** - Information about the current command. Read-only.
36+
- **`$PSCmdlet`** - Cmdlet object for advanced functions. Read-only.
37+
38+
### Other Common Automatic Variables
39+
40+
- `$true`, `$false`, `$null` - Boolean and null constants
41+
- `$HOME`, `$PSHome`, `$PWD` - Path-related variables
42+
- `$PID` - Process ID of the current PowerShell session
43+
- `$Host` - Host application object
44+
- `$PSVersionTable` - PowerShell version information
45+
46+
For a complete list, see: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables
47+
48+
## Best Practices
49+
50+
### ❌ Bad - Using Automatic Variable Names
51+
52+
```powershell
53+
# Bad: $matches is an automatic variable used for regex capture groups
54+
$matches = Select-String -Path $file -Pattern $pattern
55+
56+
# Bad: $args is an automatic variable for undeclared parameters
57+
$args = Get-ChildItem
58+
59+
# Bad: $input is an automatic variable for pipeline input
60+
$input = Read-Host "Enter value"
61+
```
62+
63+
### ✅ Good - Using Descriptive Alternative Names
64+
65+
```powershell
66+
# Good: Use descriptive names that avoid conflicts
67+
$matchedLines = Select-String -Path $file -Pattern $pattern
68+
69+
# Good: Use specific names for arguments
70+
$arguments = Get-ChildItem
71+
72+
# Good: Use specific names for user input
73+
$userInput = Read-Host "Enter value"
74+
```
75+
76+
## Naming Alternatives
77+
78+
When you encounter a situation where you might use an automatic variable name, use these alternatives:
79+
80+
| Avoid | Use Instead |
81+
|-------|-------------|
82+
| `$matches` | `$matchedLines`, `$matchResults`, `$regexMatches` |
83+
| `$args` | `$arguments`, `$parameters`, `$commandArgs` |
84+
| `$input` | `$userInput`, `$inputValue`, `$inputData` |
85+
| `$_` (outside pipeline) | Use a named parameter or explicit variable |
86+
| `$Error` (reassignment) | Don't reassign; use `$Error.Clear()` if needed |
87+
88+
## How to Check
89+
90+
### PSScriptAnalyzer Rule
91+
92+
PSScriptAnalyzer has a built-in rule that detects assignments to automatic variables:
93+
94+
```powershell
95+
# This will trigger PSAvoidAssignmentToAutomaticVariable
96+
$matches = Get-Something
97+
```
98+
99+
**Rule ID**: PSAvoidAssignmentToAutomaticVariable
100+
101+
### Manual Review
102+
103+
When writing PowerShell code, always:
104+
1. Avoid variable names that match PowerShell keywords or automatic variables
105+
2. Use descriptive, specific names that clearly indicate the variable's purpose
106+
3. Run PSScriptAnalyzer on your code before committing
107+
4. Review code for variable naming during PR reviews
108+
109+
## Examples from the Codebase
110+
111+
### Example 1: Regex Matching
112+
113+
```powershell
114+
# ❌ Bad - Overwrites automatic $matches variable
115+
$matches = [regex]::Matches($content, $pattern)
116+
117+
# ✅ Good - Uses descriptive name
118+
$regexMatches = [regex]::Matches($content, $pattern)
119+
```
120+
121+
### Example 2: Select-String Results
122+
123+
```powershell
124+
# ❌ Bad - Conflicts with automatic $matches
125+
$matches = Select-String -Path $file -Pattern $pattern
126+
127+
# ✅ Good - Clear and specific
128+
$matchedLines = Select-String -Path $file -Pattern $pattern
129+
```
130+
131+
### Example 3: Collecting Arguments
132+
133+
```powershell
134+
# ❌ Bad - Conflicts with automatic $args
135+
function Process-Items {
136+
$args = $MyItems
137+
# ... process items
138+
}
139+
140+
# ✅ Good - Descriptive parameter name
141+
function Process-Items {
142+
[CmdletBinding()]
143+
param(
144+
[Parameter(ValueFromRemainingArguments)]
145+
[string[]]$Items
146+
)
147+
# ... process items
148+
}
149+
```
150+
151+
## References
152+
153+
- [PowerShell Automatic Variables Documentation](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables)
154+
- [PSScriptAnalyzer Rules](https://github.com/PowerShell/PSScriptAnalyzer/blob/master/docs/Rules/README.md)
155+
- [PowerShell Best Practices](https://learn.microsoft.com/powershell/scripting/developer/cmdlet/strongly-encouraged-development-guidelines)
156+
157+
## Summary
158+
159+
**Key Takeaway**: Always use descriptive, specific variable names that clearly indicate their purpose and avoid conflicts with PowerShell's automatic variables. When in doubt, choose a longer, more descriptive name over a short one that might conflict.

0 commit comments

Comments
 (0)