Merge branch 'master' into copilot/address-inline-comment-feedback

This commit is contained in:
Travis Plunk authored and GitHub committed 2026-10-06 15:43:43 -04:00
commit 921ea55938
2485 files changed
+429113 -56083

No files matched your search

+64
View File
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<SiPolicy xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:schemas-microsoft-com:sipolicy">
<VersionEx>10.4.0.0</VersionEx>
<PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID>
<PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>
<!-- Do not inherit the default policy: this policy must accept only the signer below. -->
<Rules />
<EKUs>
<EKU ID="ID_EKU_WINDOWS" Value="010A2B0601040182370A0306" FriendlyName="Windows EKU - 1.3.6.1.4.1.311.10.3.6" />
<EKU ID="ID_EKU_WHQL" Value="010A2B0601040182370A0305" FriendlyName="WHQL EKU - 1.3.6.1.4.1.311.10.3.5" />
<EKU ID="ID_EKU_ELAM" Value="010A2B0601040182373D0401" FriendlyName="Early Launch AntiMalware EKU - 1.3.6.1.4.1.311.61.4.1" />
<EKU ID="ID_EKU_HAL_EXT" Value="010A2B0601040182373D0501" FriendlyName="Hardware Abstraction Layer EKU - 1.3.6.1.4.1.311.61.5.1" />
<EKU ID="ID_EKU_RT_EXT" Value="010A2B0601040182370A0315" FriendlyName="Windows RT EKU - 1.3.6.1.4.1.311.10.3.21" />
<EKU ID="ID_EKU_STORE" Value="010A2B0601040182374C0301" FriendlyName="Windows Store EKU - 1.3.6.1.4.1.311.76.3.1" />
<EKU ID="ID_EKU_DCODEGEN" Value="010A2B0601040182374C0501" FriendlyName="Dynamic Code Generation EKU - 1.3.6.1.4.1.311.76.5.1" />
<EKU ID="ID_EKU_AM" Value="010A2B0601040182374C0B01" FriendlyName="AntiMalware EKU - 1.3.6.1.4.1.311.76.11.1" />
<EKU ID="ID_EKU_ENCLAVE" Value="010A2B0601040182370A032A" FriendlyName="Enclave EKU - 1.3.6.1.4.1.311.10.3.42" />
</EKUs>
<FileRules>
<FileAttrib ID="ID_FILEATTRIB_REFRESH_POLICY" FriendlyName="RefreshPolicy.exe FileAttribute" FileName="RefreshPolicy.exe" MinimumFileVersion="10.0.19042.0" />
</FileRules>
<!--
The vPack pipeline signs every .dll, .exe and every signed .ps1/.psm1/.psd1/.ps1xml with the
Windows build tools certificate (windows_build_tools_cert_id / CP-458204). This policy therefore
allows the "Windows Internal Build Tools CodeSign" publisher and nothing else, so that any file
that is not signed with the tools certificate is reported by CodeSign Validation.
CodeSign Validation evaluates these payload files under the user mode (UMCI) scenario.
-->
<Signers>
<Signer Name="Windows Internal Build Tools PCA 2020" ID="ID_SIGNER_S_0">
<CertRoot Type="TBS" Value="0B0692273CF07E96C7A9EC4177E3044368B383CBF8E03BAC215C3E3BC5C203482262169804ACD1F473C57C2831A3F191" />
<CertPublisher Value="Windows Internal Build Tools CodeSign" />
</Signer>
</Signers>
<SigningScenarios>
<SigningScenario ID="ID_SIGNINGSCENARIO_KMCI" FriendlyName="Kernel Mode Signing Scenario" Value="131">
<ProductSigners />
</SigningScenario>
<SigningScenario ID="ID_SIGNINGSCENARIO_UMCI" FriendlyName="User Mode Signing Scenario" Value="12">
<ProductSigners>
<AllowedSigners>
<AllowedSigner SignerId="ID_SIGNER_S_0" />
</AllowedSigners>
</ProductSigners>
</SigningScenario>
</SigningScenarios>
<UpdatePolicySigners />
<CiSigners>
<CiSigner SignerId="ID_SIGNER_S_0" />
</CiSigners>
<HvciOptions>0</HvciOptions>
<Settings>
<Setting Provider="PolicyInfo" Key="Information" ValueName="Name">
<Value>
<String>CodeSignCustomPolicy_2026-08-31</String>
</Value>
</Setting>
<Setting Provider="PolicyInfo" Key="Information" ValueName="Id">
<Value>
<String>2026-08-31</String>
</Value>
</Setting>
</Settings>
</SiPolicy>
+4 -12
View File
@@ -91,7 +91,7 @@ To run the link-checker, follow these steps:
1. Issues marked as [`First-Time-Issue`][first-time-issue],
are identified as being easy and a great way to learn about this project and making
contributions.
### Finding or creating an issue
1. Follow the instructions in [Contributing to Issues][contribute-issues] to find or open an issue.
@@ -264,18 +264,10 @@ Please see PowerShell [Testing Guidelines - Running Tests Outside of CI][running
* Our CI contains automated spell checking and link checking for Markdown files. If there is any false-positive,
[run the spell checker command-line tool in interactive mode](#spell-checking-documentation)
to add words to the `.spelling` file.
* Our packaging test may not pass and ask you to update `files.wxs` file if you add/remove/update nuget package references or add/remove assert files.
You could update the file manually in accordance with messages in the test log file. Or you can use automatically generated file. To get the file you should build the msi package locally:
```powershell
Import-Module .\build.psm1
Start-PSBuild -Clean -CrossGen -PSModuleRestore -Runtime win7-x64 -Configuration Release -ReleaseTag <release tag>
Import-Module .\tools\packaging
Start-PSPackage -Type msi -ReleaseTag <release tag> -WindowsRuntime 'win7-x64' -SkipReleaseChecks
```
Last command will report where new file is located.
You could update the `.spelling` file manually in accordance with messages in the test log file, or
[run the spell checker command-line tool in interactive mode](#spell-checking-documentation)
to add the false-positive words directly.
#### Pull Request - Workflow
+2 -2
View File
@@ -13,7 +13,7 @@ runs:
if: github.event_name != 'PullRequest'
run: Write-Host "##vso[build.updatebuildnumber]$env:BUILD_SOURCEBRANCHNAME-$env:BUILD_SOURCEVERSION-$((get-date).ToString("yyyyMMddhhmmss"))"
shell: pwsh
- uses: actions/setup-dotnet@v4
- uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
global-json-file: ./global.json
- name: Bootstrap
@@ -34,7 +34,7 @@ runs:
Invoke-CIBuild
shell: pwsh
- name: Upload build artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: build
path: ${{ runner.workspace }}/build
@@ -13,6 +13,9 @@ outputs:
files:
description: 'JSON array of changed file paths'
value: ${{ steps.get-files.outputs.files }}
files_path:
description: 'Path to temp file containing the JSON array of changed file paths'
value: ${{ steps.get-files.outputs.files_path }}
count:
description: 'Number of changed files'
value: ${{ steps.get-files.outputs.count }}
@@ -21,7 +24,7 @@ runs:
steps:
- name: Get changed files
id: get-files
uses: actions/github-script@v7
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
with:
script: |
const eventTypes = '${{ inputs.event-types }}'.split(',').map(t => t.trim());
@@ -109,7 +112,17 @@ runs:
core.endGroup();
console.log(`Found ${changedFiles.length} changed files`);
// Write files to a temp file to avoid exceeding ARG_MAX for large PRs
const fs = require('fs');
const path = require('path');
const tempDir = process.env.RUNNER_TEMP || '/tmp';
const tempFile = path.join(tempDir, 'changed-files.json');
fs.writeFileSync(tempFile, JSON.stringify(changedFiles));
console.log(`File list written to ${tempFile}`);
core.setOutput('files', JSON.stringify(changedFiles));
core.setOutput('files_path', tempFile);
core.setOutput('count', changedFiles.length);
branding:
@@ -40,13 +40,17 @@ runs:
id: verify
shell: pwsh
env:
CHANGED_FILES_JSON: ${{ steps.changed-files.outputs.files }}
CHANGED_FILES_PATH: ${{ steps.changed-files.outputs.files_path }}
run: |
Write-Host "Starting markdown link verification..." -ForegroundColor Cyan
# Get changed markdown files from environment variable (secure against injection)
$changedFilesJson = $env:CHANGED_FILES_JSON
$changedFiles = $changedFilesJson | ConvertFrom-Json
# Read changed markdown files from temp file to avoid ARG_MAX limits with large PRs
$changedFilesPath = $env:CHANGED_FILES_PATH
if ($changedFilesPath -and (Test-Path $changedFilesPath)) {
$changedFiles = @(Get-Content $changedFilesPath -Raw | ConvertFrom-Json)
} else {
$changedFiles = @()
}
if ($changedFiles.Count -eq 0) {
Write-Host "No markdown files changed, skipping verification" -ForegroundColor Yellow
@@ -21,12 +21,15 @@ runs:
id: check
shell: pwsh
env:
CHANGED_FILES_JSON: ${{ steps.changed-files.outputs.files }}
CHANGED_FILES_PATH: ${{ steps.changed-files.outputs.files_path }}
run: |
# Get changed files from environment variable (secure against injection)
$changedFilesJson = $env:CHANGED_FILES_JSON
# Ensure we always have an array (ConvertFrom-Json returns null for empty JSON arrays)
$changedFiles = @($changedFilesJson | ConvertFrom-Json)
# Read changed files from temp file to avoid ARG_MAX limits with large PRs
$changedFilesPath = $env:CHANGED_FILES_PATH
if ($changedFilesPath -and (Test-Path $changedFilesPath)) {
$changedFiles = @(Get-Content $changedFilesPath -Raw | ConvertFrom-Json)
} else {
$changedFiles = @()
}
# Import ci.psm1 and run the check
Import-Module "$env:GITHUB_WORKSPACE/tools/ci.psm1" -Force
@@ -39,9 +39,9 @@ runs:
- name: Check if GitHubWorkflowChanges is present
id: filter
uses: actions/github-script@v7.0.1
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
FILES_JSON: ${{ steps.get-files.outputs.files }}
FILES_PATH: ${{ steps.get-files.outputs.files_path }}
with:
github-token: ${{ inputs.GITHUB_TOKEN }}
script: |
@@ -60,8 +60,15 @@ runs:
return;
}
// Get files from environment variable (secure against injection)
const files = JSON.parse(process.env.FILES_JSON || '[]');
// Read files from temp file to avoid ARG_MAX limits with large PRs
const fs = require('fs');
const filesPath = process.env.FILES_PATH;
let files = [];
if (filesPath && fs.existsSync(filesPath)) {
files = JSON.parse(fs.readFileSync(filesPath, 'utf8'));
} else {
console.log('Warning: files_path not found, no files to analyze');
}
// Calculate hash for verification (matches get-changed-files action)
const crypto = require('crypto');
@@ -105,6 +112,9 @@ runs:
const globalConfigChanged = files.some(file => file === '.globalconfig' || file === 'nuget.config' || file === 'global.json');
console.log(`✓ Global config changed: ${globalConfigChanged}`);
const localizationConfigChanged = files.some(file => file === 'Localize/LocProject.json');
console.log(`✓ Localization config changed: ${localizationConfigChanged}`);
const packagingChanged = files.some(file =>
file === '.github/workflows/windows-ci.yml' ||
file === '.github/workflows/linux-ci.yml' ||
@@ -121,7 +131,7 @@ runs:
toolsCiPsm1Changed;
console.log(`→ Packaging changed: ${packagingChanged}`);
const source = mainSourceChanged || toolsChanged || githubChanged || propsChanged || testsChanged || globalConfigChanged;
const source = mainSourceChanged || toolsChanged || githubChanged || propsChanged || testsChanged || globalConfigChanged || localizationConfigChanged;
console.log(`→ Source (composite): ${source}`);
core.endGroup();
@@ -11,7 +11,7 @@ runs:
Show-Environment
shell: pwsh
- uses: actions/setup-dotnet@v5
- uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0
with:
global-json-file: ./global.json
@@ -48,21 +48,21 @@ runs:
shell: pwsh
- name: Upload deb packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: packages-deb
path: ${{ runner.workspace }}/packages/*.deb
if-no-files-found: ignore
- name: Upload rpm packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: packages-rpm
path: ${{ runner.workspace }}/packages/*.rpm
if-no-files-found: ignore
- name: Upload tar.gz packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: packages-tar
path: ${{ runner.workspace }}/packages/*.tar.gz
+3 -3
View File
@@ -29,7 +29,7 @@ runs:
shell: pwsh
- name: Download Build Artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: "${{ github.workspace }}"
@@ -42,7 +42,7 @@ runs:
Write-LogGroupEnd -Title 'Artifacts Directory'
shell: pwsh
- uses: actions/setup-dotnet@v4
- uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
global-json-file: ./global.json
@@ -101,7 +101,7 @@ runs:
Write-LogGroupEnd -Title 'Bootstrap'
- name: Extract Files
uses: actions/github-script@v7.0.0
uses: actions/github-script@e69ef5462fd455e02edcaf4dd7708eda96b9eda0 # v7.0.0
env:
DESTINATION_FOLDER: "${{ github.workspace }}/bins"
ARCHIVE_FILE_PATTERNS: "${{ github.workspace }}/build/build.zip"
@@ -21,7 +21,7 @@ runs:
- name: Upload testResults artifact
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: junit-pester-${{ inputs.name }}
path: ${{ runner.workspace }}/testResults
@@ -24,6 +24,7 @@ $testIgnoredCount = 0
$testSkippedCount = 0
$testInvalidCount = 0
# Process test results and generate annotations for failures
Get-ChildItem -Path "${TestResultsFolder}/*.xml" -Recurse | ForEach-Object {
$results = [xml] (get-content $_.FullName)
@@ -35,6 +36,61 @@ Get-ChildItem -Path "${TestResultsFolder}/*.xml" -Recurse | ForEach-Object {
$testIgnoredCount += [int]$results.'test-results'.ignored
$testSkippedCount += [int]$results.'test-results'.skipped
$testInvalidCount += [int]$results.'test-results'.invalid
# Generate GitHub Actions annotations for test failures
# Select failed test cases
if ("System.Xml.XmlDocumentXPathExtensions" -as [Type]) {
$failures = [System.Xml.XmlDocumentXPathExtensions]::SelectNodes($results.'test-results', './/test-case[@result = "Failure"]')
}
else {
$failures = $results.SelectNodes('.//test-case[@result = "Failure"]')
}
foreach ($testfail in $failures) {
$description = $testfail.description
$testName = $testfail.name
$message = $testfail.failure.message
$stack_trace = $testfail.failure.'stack-trace'
# Parse stack trace to get file and line info
$fileInfo = Get-PesterFailureFileInfo -StackTraceString $stack_trace
if ($fileInfo.File) {
# Convert absolute path to relative path for GitHub Actions
$filePath = $fileInfo.File
# GitHub Actions expects paths relative to the workspace root
if ($env:GITHUB_WORKSPACE) {
$workspacePath = $env:GITHUB_WORKSPACE
if ($filePath.StartsWith($workspacePath)) {
$filePath = $filePath.Substring($workspacePath.Length).TrimStart('/', '\')
# Normalize to forward slashes for consistency
$filePath = $filePath -replace '\\', '/'
}
}
# Create annotation title
$annotationTitle = "Test Failure: $description / $testName"
# Build the annotation message
$annotationMessage = $message -replace "`n", "%0A" -replace "`r"
# Build and output the workflow command
$workflowCommand = "::error file=$filePath"
if ($fileInfo.Line) {
$workflowCommand += ",line=$($fileInfo.Line)"
}
$workflowCommand += ",title=$annotationTitle::$annotationMessage"
Write-Host $workflowCommand
# Output a link to the test run
if ($env:GITHUB_SERVER_URL -and $env:GITHUB_REPOSITORY -and $env:GITHUB_RUN_ID) {
$logUrl = "$($env:GITHUB_SERVER_URL)/$($env:GITHUB_REPOSITORY)/actions/runs/$($env:GITHUB_RUN_ID)"
Write-Host "Test logs: $logUrl"
}
}
}
}
@"
+3 -3
View File
@@ -29,7 +29,7 @@ runs:
shell: pwsh
- name: Download Build Artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
path: "${{ github.workspace }}"
@@ -42,7 +42,7 @@ runs:
Write-LogGroupEnd -Title 'Artifacts Directory'
shell: pwsh
- uses: actions/setup-dotnet@v4
- uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
global-json-file: .\global.json
@@ -70,7 +70,7 @@ runs:
Set-GWVariable -Name "DSC_ROOT" -Value $dscRoot
- name: Bootstrap
shell: powershell
shell: pwsh
run: |-
Import-Module ./build.psm1
Write-LogGroupStart -Title 'Bootstrap'
+180
View File
@@ -0,0 +1,180 @@
---
name: SplitADOPipelines
description: This agent will implement and restructure the repository's existing ADO pipelines into Official and NonOfficial pipelines.
tools: ['vscode', 'execute', 'read', 'agent', 'edit', 'search', 'todo']
---
This agent will implement and restructure the repository's existing ADO pipelines into Official and NonOfficial pipelines.
A repository will have under the .pipelines directory a series of yaml files that define the ADO pipelines for the repository.
First confirm if the pipelines are using a toggle switch for Official and NonOfficial. This will look something like this
```yaml
parameters:
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates' ) }}
```
Followed by:
```yaml
extends:
template: ${{ variables.templateFile }}
```
This is an indicator that this work needs to be done. This toggle switch is no longer allowed and the templates need to be hard coded.
## Template Reference Convention (MUST follow)
All `- template:` references to files **inside this repo** must use the **absolute** form anchored at the repo root, with the `@self` suffix:
```yaml
- template: /.pipelines/templates/<path>/<file>.yml@self
```
Do **not** use relative paths such as `templates/...`, `../templates/...`, or bare filenames. Rationale:
- Absolute paths resolve identically regardless of where the referring file lives, so moving a pipeline file between directories (for example, into `.pipelines/NonOfficial/`) does not silently break includes.
- Relative paths are resolved by Azure DevOps against the directory of the referring file, which has caused real outages in this repo when a relative include was composed into a nonexistent nested path like `.pipelines/templates/stages/.pipelines/templates/...`.
- The majority of existing includes already use the absolute form; keeping new work consistent reduces review burden.
The only acceptable non-absolute references are to external repositories resolved via the `resources.repositories` block, for example `v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates`.
## Refactoring Steps
### Step 1: Extract Shared Templates
For each pipeline file that uses the toggle switch pattern (e.g., `PowerShell-Packages-Official.yml`):
1. Create the `.pipelines/templates/variables` and `.pipelines/templates/stages` directories if they don't exist
2. Extract the **variables section** into `.pipelines/templates/variables/PowerShell-Packages-Variables.yml`
3. Extract the **stages section** into `.pipelines/templates/stages/PowerShell-Packages-Stages.yml`
**IMPORTANT**: Only extract the `variables:` and `stages:` sections. All other sections (parameters, resources, extends, etc.) remain in the pipeline files.
### Step 2: Create Official Pipeline (In-Place Refactoring)
The original toggle-based file becomes the Official pipeline:
1. **Keep the file in its original location** (e.g., `.pipelines/PowerShell-Packages-Official.yml` stays where it is)
2. Remove the toggle switch parameter (`templateFile` parameter)
3. Hard-code the Official template reference:
```yaml
extends:
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates
```
4. Replace the `variables:` section with a template reference:
```yaml
variables:
- template: /.pipelines/templates/variables/PowerShell-Packages-Variables.yml@self
```
5. Replace the `stages:` section with a template reference:
```yaml
stages:
- template: /.pipelines/templates/stages/PowerShell-Packages-Stages.yml@self
```
### Step 3: Create NonOfficial Pipeline
1. Create `.pipelines/NonOfficial` directory if it doesn't exist
2. Create the NonOfficial pipeline file (e.g., `.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml`)
3. Copy the structure from the refactored Official pipeline
4. Hard-code the NonOfficial template reference:
```yaml
extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
```
5. Reference the same shared templates:
```yaml
variables:
- template: /.pipelines/templates/variables/PowerShell-Packages-Variables.yml@self
stages:
- template: /.pipelines/templates/stages/PowerShell-Packages-Stages.yml@self
```
**Note**: Always use **absolute** template paths of the form `/.pipelines/templates/...@self`. Do not use relative paths like `templates/...` or `../templates/...`. Absolute paths are anchored at the repo root and resolve consistently from any referring file, preventing breakage when files are moved between directories.
### Step 4: Link NonOfficial Pipelines to NonOfficial Dependencies
After creating NonOfficial pipelines, ensure they consume artifacts from other **NonOfficial** pipelines, not Official ones.
1. **Check the `resources:` section** in each NonOfficial pipeline for `pipelines:` dependencies
2. **Identify Official pipeline references** that need to be changed to NonOfficial
3. **Update the `source:` field** to point to the NonOfficial version
**Example Problem:** NonOfficial pipeline pointing to Official dependency
```yaml
resources:
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated Binaries-Official' # ❌ Wrong - Official!
```
**Solution:** Update to NonOfficial dependency
```yaml
resources:
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated Binaries-NonOfficial' # ✅ Correct - NonOfficial!
```
**IMPORTANT**: The `source:` field must match the **exact ADO pipeline definition name** as it appears in Azure DevOps, not necessarily the file name.
### Step 5: Configure Release Environment Parameters (NonAzure Only)
**This step only applies if the pipeline uses `category: NonAzure` in the release configuration.**
If you detect this pattern in the original pipeline:
```yaml
extends:
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates # or NonOfficial
parameters:
release:
category: NonAzure
```
Then you must configure the `ob_release_environment` parameter when referencing the stages template.
#### Official Pipeline Configuration
In the Official pipeline (e.g., `.pipelines/PowerShell-Packages-Official.yml`):
```yaml
stages:
- template: /.pipelines/templates/stages/PowerShell-Packages-Stages.yml@self
parameters:
ob_release_environment: Production
```
#### NonOfficial Pipeline Configuration
In the NonOfficial pipeline (e.g., `.pipelines/NonOfficial/PowerShell-Packages-NonOfficial.yml`):
```yaml
stages:
- template: /.pipelines/templates/stages/PowerShell-Packages-Stages.yml@self
parameters:
ob_release_environment: Test
```
#### Update Stages Template to Accept Parameter
The extracted stages template (e.g., `.pipelines/templates/stages/PowerShell-Packages-Stages.yml`) must declare the parameter at the top:
```yaml
parameters:
- name: ob_release_environment
type: string
stages:
# ... rest of stages configuration using ${{ parameters.ob_release_environment }}
```
**IMPORTANT**:
- Only configure this for pipelines with `category: NonAzure`
- Official pipelines always use `ob_release_environment: Production`
- NonOfficial pipelines always use `ob_release_environment: Test`
- The stages template must accept this parameter and use it in the appropriate stage configurations
@@ -0,0 +1,198 @@
---
applyTo:
- "**/*.Tests.ps1"
---
# Pester Set-ItResult Pattern for Pending and Skipped Tests
## Purpose
This instruction explains when and how to use `Set-ItResult` in Pester tests to mark tests as Pending or Skipped dynamically within test execution.
## When to Use Set-ItResult
Use `Set-ItResult` when you need to conditionally mark a test as Pending or Skipped based on runtime conditions that can't be determined at test definition time.
### Pending vs Skipped
**Pending**: Use for tests that should be enabled but temporarily can't run due to:
- Intermittent external service failures (network, APIs)
- Known bugs being fixed
- Missing features being implemented
- Environmental issues that are being resolved
**Skipped**: Use for tests that aren't applicable to the current environment:
- Platform-specific tests running on wrong platform
- Tests requiring specific hardware/configuration not present
- Tests requiring elevated permissions when not available
- Feature-specific tests when feature is disabled
## Pattern
### Basic Usage
```powershell
It "Test description" {
if ($shouldBePending) {
Set-ItResult -Pending -Because "Explanation of why test is pending"
return
}
if ($shouldBeSkipped) {
Set-ItResult -Skipped -Because "Explanation of why test is skipped"
return
}
# Test code here
}
```
### Important: Always Return After Set-ItResult
After calling `Set-ItResult`, you **must** return from the test to prevent further execution:
```powershell
It "Test that checks environment" {
if ($env:SKIP_TESTS -eq 'true') {
Set-ItResult -Skipped -Because "SKIP_TESTS environment variable is set"
return # This is required!
}
# Test assertions
$result | Should -Be $expected
}
```
**Why?** Without `return`, the test continues executing and may fail with errors unrelated to the pending/skipped condition.
## Examples from the Codebase
### Example 1: Pending for Intermittent Network Issues
```powershell
It "Validate Update-Help for module" {
if ($markAsPending) {
Set-ItResult -Pending -Because "Update-Help from the web has intermittent connectivity issues. See issues #2807 and #6541."
return
}
Update-Help -Module $moduleName -Force
# validation code...
}
```
### Example 2: Skipped for Missing Environment
```powershell
It "Test requires CI environment" {
if (-not $env:CI) {
Set-ItResult -Skipped -Because "Test requires CI environment to safely install Pester"
return
}
Install-CIPester -ErrorAction Stop
}
```
### Example 3: Pending for Platform-Specific Issue
```powershell
It "Clear-Host works correctly" {
if ($IsARM64) {
Set-ItResult -Pending -Because "ARM64 runs in non-interactively mode and Clear-Host does not work."
return
}
& { Clear-Host; 'hi' } | Should -BeExactly 'hi'
}
```
### Example 4: Skipped for Missing Feature
```powershell
It "Test ACR authentication" {
if ($env:ACRTESTS -ne 'true') {
Set-ItResult -Skipped -Because "The tests require the ACRTESTS environment variable to be set to 'true' for ACR authentication."
return
}
$psgetModuleInfo = Find-PSResource -Name $ACRTestModule -Repository $ACRRepositoryName
# test assertions...
}
```
## Alternative: Static -Skip and -Pending Parameters
For conditions that can be determined at test definition time, use the static parameters instead:
```powershell
# Static skip - condition known at definition time
It "Windows-only test" -Skip:(-not $IsWindows) {
# test code
}
# Static pending - always pending
It "Test for feature being implemented" -Pending {
# test code that will fail until feature is done
}
```
**Use Set-ItResult when**:
- Condition depends on runtime state
- Condition is determined inside a helper function
- Need to check multiple conditions sequentially
**Use static parameters when**:
- Condition is known at test definition
- Condition doesn't change during test run
- Want Pester to show the condition in test discovery
## Best Practices
1. **Always include -Because parameter** with a clear explanation
2. **Always return after Set-ItResult** to prevent further execution
3. **Reference issues or documentation** when relevant (e.g., "See issue #1234")
4. **Be specific in the reason** - explain what's wrong and what's needed
5. **Use Pending sparingly** - it indicates a problem that should be fixed
6. **Prefer Skipped over Pending** when test truly isn't applicable
## Common Mistakes
### ❌ Mistake 1: Forgetting to Return
```powershell
It "Test" {
if ($condition) {
Set-ItResult -Pending -Because "Reason"
# Missing return - test code will still execute!
}
$value | Should -Be $expected # This runs and fails
}
```
### ❌ Mistake 2: Vague Reason
```powershell
Set-ItResult -Pending -Because "Doesn't work" # Too vague
```
### ✅ Correct:
```powershell
It "Test" {
if ($condition) {
Set-ItResult -Pending -Because "Update-Help has intermittent network timeouts. See issue #2807."
return
}
$value | Should -Be $expected
}
```
## See Also
- [Pester Documentation: Set-ItResult](https://pester.dev/docs/commands/Set-ItResult)
- [Pester Documentation: It](https://pester.dev/docs/commands/It)
- Examples in the codebase:
- `test/powershell/Host/ConsoleHost.Tests.ps1`
- `test/infrastructure/ciModule.Tests.ps1`
- `tools/packaging/releaseTests/sbom.tests.ps1`
@@ -0,0 +1,299 @@
---
applyTo: "**/*.Tests.ps1"
---
# Pester Test Status Meanings and Working Tests
## Purpose
This guide clarifies Pester test outcomes and what it means for a test to be "working" - which requires both **passing** AND **actually validating functionality**.
## Test Statuses in Pester
### Passed ✓
**Status Code**: `Passed`
**Exit Result**: Test ran successfully, all assertions passed
**What it means**:
- Test executed without errors
- All `Should` statements evaluated to true
- Test setup and teardown completed without issues
- Test is **validating** the intended functionality
**What it does NOT mean**:
- The feature is working (assertions could be wrong)
- The test is meaningful (could be testing wrong thing)
- The test exercises all code paths
### Failed ✗
**Status Code**: `Failed`
**Exit Result**: Test ran but assertions failed
**What it means**:
- Test executed but an assertion returned false
- Expected value did not match actual value
- Test detected a problem with the functionality
**Examples**:
```
Expected $true but got $false
Expected 5 items but got 3
Expected no error but got: Cannot find parameter
```
### Error ⚠
**Status Code**: `Error`
**Exit Result**: Test crashed with an exception
**What it means**:
- Test failed to complete
- An exception was thrown during test execution
- Could be in test setup, test body, or test cleanup
- Often indicates environmental issue, not code functional issue
**Examples**:
```
Cannot bind argument to parameter 'Path' because it is null
File not found: C:\expected\config.json
Access denied writing to registry
```
### Pending ⏳
**Status Code**: `Pending`
**Exit Result**: Test ran but never completed assertions
**What it means**:
- Test was explicitly marked as not ready to run
- `Set-ItResult -Pending` was called
- Used to indicate: known bugs, missing features, environmental issues
**When to use Pending**:
- Test for feature in development
- Test disabled due to known bug (issue #1234)
- Test disabled due to intermittent failures being fixed
- Platform-specific issues being resolved
**⚠️ WARNING**: Pending tests are NOT validating functionality. They hide problems.
### Skipped ⊘
**Status Code**: `Skipped`
**Exit Result**: Test did not run (detected at start)
**What it means**:
- Test was intentionally not executed
- `-Skip` parameter or `It -Skip:$condition` was used
- Environment doesn't support this test
**When to use Skip**:
- Test not applicable to current platform (Windows-only test on Linux)
- Test requires feature that's not available (admin privileges)
- Test requires specific configuration not present
**Difference from Pending**:
- **Skip**: "This test shouldn't run here" (known upfront)
- **Pending**: "This test should eventually run but can't now"
### Ignored ✛
**Status Code**: `Ignored`
**Exit Result**: Test marked as not applicable
**What it means**:
- Test has `[Ignore("reason")]` attribute
- Test is permanently disabled in this location
- Not the same as Skipped (which is conditional)
**When to use Ignore**:
- Test for deprecated feature
- Test for bug that won't be fixed
- Test moved to different test file
---
## What Does "Working" Actually Mean?
A test is **working** when it meets BOTH criteria:
### 1. **Test Status is PASSED** ✓
```powershell
It "Test name" {
# Test executes
# All assertions pass
# Returns Passed status
}
```
### 2. **Test Actually Validates Functionality**
```powershell
# ✓ GOOD: Tests actual functionality
It "Get-Item returns files from directory" -Tags @('Unit') {
$testDir = New-Item -ItemType Directory -Force
New-Item -Path $testDir -Name "file.txt" -ItemType File | Out-Null
$result = Get-Item -Path "$testDir\file.txt"
$result.Name | Should -Be "file.txt"
$result | Should -Exist
Remove-Item $testDir -Recurse -Force
}
# ✗ BAD: Returns Passed but doesn't validate functionality
It "Get-Item returns files from directory" -Tags @('Unit') {
$result = Get-Item -Path somepath # May not exist, may not actually test
$result | Should -Not -BeNullOrEmpty # Too vague
}
# ✗ BAD: Test marked Pending - validation is hidden
It "Get-Item returns files from directory" -Tags @('Unit') {
Set-ItResult -Pending -Because "File system not working"
return
# No validation happens at all
}
```
---
## The Problem with Pending Tests
### Why Pending Tests Hide Problems
```powershell
# BAD: Test marked Pending - looks like "working" status but validation is skipped
It "Download help from web" {
Set-ItResult -Pending -Because "Web connectivity issues"
return
# This code never runs:
Update-Help -Module PackageManagement -Force -ErrorAction Stop
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
```
**Result**:
- ✗ Feature is broken (Update-Help fails)
- ✓ Test shows "Pending" (looks acceptable)
- ✗ Problem is hidden and never fixed
### The Right Approach
**Option A: Fix the root cause**
```powershell
It "Download help from web" {
# Use local assets that are guaranteed to work
Update-Help -Module PackageManagement -SourcePath ./assets -Force -ErrorAction Stop
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
```
**Option B: Gracefully skip when unavailable**
```powershell
It "Download help from web" -Skip:$(-not $hasInternet) {
Update-Help -Module PackageManagement -Force -ErrorAction Stop
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
```
**Option C: Add retry logic for intermittent issues**
```powershell
It "Download help from web" {
$maxRetries = 3
$attempt = 0
while ($attempt -lt $maxRetries) {
try {
Update-Help -Module PackageManagement -Force -ErrorAction Stop
break
}
catch {
$attempt++
if ($attempt -ge $maxRetries) { throw }
Start-Sleep -Seconds 2
}
}
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
```
---
## Test Status Summary Table
| Status | Passed? | Validates? | Counts as "Working"? | Use When |
|--------|---------|------------|----------------------|----------|
| **Passed** | ✓ | ✓ | **YES** | Feature is working and test proves it |
| **Failed** | ✗ | ✓ | NO | Feature is broken or test has wrong expectation |
| **Error** | ✗ | ✗ | NO | Test infrastructure broken, can't validate |
| **Pending** | - | ✗ | **NO** ⚠️ | Temporary - test should eventually pass |
| **Skipped** | - | ✗ | NO | Test not applicable to this environment |
| **Ignored** | - | ✗ | NO | Test permanently disabled |
---
## Recommended Patterns
### Pattern 1: Resilient Test with Fallback
```powershell
It "Feature works with web or local source" {
$useLocal = $false
try {
Update-Help -Module Package -Force -ErrorAction Stop
}
catch {
$useLocal = $true
Update-Help -Module Package -SourcePath ./assets -Force -ErrorAction Stop
}
# Validate functionality regardless of source
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
```
### Pattern 2: Conditional Skip with Clear Reason
```powershell
Describe "Update-Help from Web" -Skip $(-not (Test-InternetConnectivity)) {
It "Downloads help successfully" {
Update-Help -Module PackageManagement -Force -ErrorAction Stop
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
}
```
### Pattern 3: Separate Suites by Dependency
```powershell
Describe "Help Content Tests - Web" {
# Tests that require internet - can be skipped if unavailable
It "Downloads from web" { ... }
}
Describe "Help Content Tests - Local" {
# Tests with local assets - should always pass
It "Loads from local assets" {
Update-Help -Module Package -SourcePath ./assets -Force
Get-Help Get-Package | Should -Not -BeNullOrEmpty
}
}
```
---
## Checklist: Is Your Test "Working"?
- [ ] Test status is **Passed** (not Pending, not Skipped, not Failed)
- [ ] Test actually **executes** the feature being tested
- [ ] Test has **specific assertions** (not just `Should -Not -BeNullOrEmpty`)
- [ ] Test includes **cleanup** (removes temp files, restores state)
- [ ] Test can run **multiple times** without side effects
- [ ] Test failure **indicates a real problem** (not flaky assertions)
- [ ] Test success **proves the feature works** (not just "didn't crash")
If any of these is false, your test may be passing but not "working" properly.
---
## See Also
- [Pester Documentation](https://pester.dev/)
- [Set-ItResult Documentation](https://pester.dev/docs/commands/Set-ItResult)
@@ -83,7 +83,7 @@ PowerShell code in GitHub Actions YAML files should be kept minimal. Move code t
**Examples**:
- `Start-PSPackage` - Create packages
- `New-MSIPackage` - Create Windows MSI
- `New-MSIXPackage` - Create Windows MSIX
- `New-DotnetSdkContainerFxdPackage` - Create container packages
**When NOT to use**:
@@ -0,0 +1,27 @@
---
applyTo:
- "**/*.ps1"
- "**/*.psm1"
---
# Script and Module File Format
These instructions define required file-level formatting for PowerShell scripts and module files in this repository.
## Copyright Header
If a change adds a new `.ps1` file or `.psm1` file or touches an existing one, the file should start with the copyright and license header and have an empty line after it, as shown in the example below:
```powershell
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
```
Do not place blank lines, comments, or code before this header.
## Requirements
- Add the copyright header when creating a new `.ps1` or `.psm1` file.
- Preserve the header when editing an existing `.ps1` or `.psm1` file.
- If an existing `.ps1` or `.psm1` file is missing the header, only modify that file to add the header if a change touches that file. Do not make a change to add the header if the file is not being modified.
@@ -0,0 +1,56 @@
id: labelAdded.clBuildPackaging.addBackportConsider
name: GitOps.PullRequestIssueManagement
description: Add backport consideration labels when CL-BuildPackaging is added to an open PR targeting master
owner:
resource: repository
disabled: false
where:
configuration:
resourceManagementConfiguration:
eventResponderTasks:
- description: Add BackPort-7.4.x-Consider when CL-BuildPackaging is added to open PR targeting master
if:
- payloadType: Pull_Request
- isOpen
- labelAdded:
label: CL-BuildPackaging
- targetsBranch:
branch: master
- not:
hasLabel:
label: BackPort-7.4.x-Consider
then:
- addLabel:
label: BackPort-7.4.x-Consider
- description: Add BackPort-7.5.x-Consider when CL-BuildPackaging is added to open PR targeting master
if:
- payloadType: Pull_Request
- isOpen
- labelAdded:
label: CL-BuildPackaging
- targetsBranch:
branch: master
- not:
hasLabel:
label: BackPort-7.5.x-Consider
then:
- addLabel:
label: BackPort-7.5.x-Consider
- description: Add BackPort-7.6.x-Consider when CL-BuildPackaging is added to open PR targeting master
if:
- payloadType: Pull_Request
- isOpen
- labelAdded:
label: CL-BuildPackaging
- targetsBranch:
branch: master
- not:
hasLabel:
label: BackPort-7.6.x-Consider
then:
- addLabel:
label: BackPort-7.6.x-Consider
onFailure:
onSuccess:
@@ -0,0 +1,524 @@
---
name: analyze-pester-failures
description: Troubleshooting guide for analyzing and investigating Pester test failures in PowerShell CI jobs. Help agents understand why tests are failing, interpret test output, navigate test result artifacts, and provide actionable recommendations for fixing test issues.
---
# Analyze Pester Test Failures
Investigate and troubleshoot Pester test failures in GitHub Actions workflows. Understand what tests are failing, why they're failing, and provide recommendations for test fixes.
| Skill | When to Use |
|-------|-----------|
| analyze-pester-failures | When investigating why Pester tests are failing in a CI job. Use when a test job shows failures and you need to understand what test failed, why it failed, what the error message means, and what might need to be fixed. Also use when asked: "why did this test fail?", "what's the test error?", "test is broken", "test failure analysis", "debug test failure", or given test failure logs and stack traces. |
## When to Use This Skill
Use this skill when you need to:
- Understand why a specific Pester test is failing
- Interpret test failure messages and error output
- Analyze test result data from CI workflow runs (XML, logs, stack traces)
- Identify the root cause of test failures (test logic, assertion failure, exception, timeout, skip/ignore reason)
- Provide recommendations for fixing failing tests
- Compare expected vs. actual test behavior
- Debug test environment issues (missing dependencies, configuration problems)
- Understand test skip/ignored/inconclusive status reasons
**Do not use this skill for:**
- General PowerShell debugging unrelated to tests
- Test infrastructure/CI setup issues (except as they affect test failure interpretation)
- Performance analysis or benchmarking (that's a different investigation)
## Quick Start
### ⚠️ CRITICAL: The Workflow Must Be Followed IN ORDER
This skill describes a **sequential 6-step analysis workflow**. Skipping steps or jumping around leads to **incomplete analysis and incorrect conclusions**.
**The Problem**: It's easy to skip to Step 4 or 5 without doing Steps 1-2, resulting in missing data and bad conclusions.
**The Solution**: Use the automated analysis script to enforce the workflow:
```powershell
# Automatically runs Steps 1-6 in order, preventing skipping
./.github/skills/analyze-pester-failures/scripts/analyze-pr-test-failures.ps1 -PR <PR_NUMBER>
# Example:
./.github/skills/analyze-pester-failures/scripts/analyze-pr-test-failures.ps1 -PR 26800
```
This script:
1. ✓ Fetches PR status automatically
2. ✓ Downloads artifacts (can't skip, depends on Step 1)
3. ✓ Extracts failures (can't skip, depends on Step 2)
4. ✓ Analyzes error messages
5. ✓ Documents context
6. ✓ Generates recommendations
**Only use the manual commands below if you fully understand the workflow.**
### Manual Workflow (for reference)
```powershell
# Step 1: Identify the failing job
gh pr view <PR_NUMBER> --json 'statusCheckRollup' | ConvertFrom-Json | Where-Object { $_.conclusion -eq 'FAILURE' }
# Step 2: Download artifacts (extract RUN_ID from Step 1)
gh run download <RUN_ID> --dir ./artifacts
gh run view <RUN_ID> --log > test-logs.txt
# Step 3-6: Extract, analyze, and interpret
# (See Analysis Workflow section below)
```
## Common Test Failure Analysis Approaches
### 1. **Interpreting Assertion Failures**
The most common test failure is when an assertion doesn't match expectations.
**Example:**
```
Expected $true but got $false at /path/to/test.ps1:42
Assertion failed: Should -Be "expected" but was "actual"
```
**How to analyze:**
- Read the assertion message: what was expected vs. what was actual?
- Check the test logic: is the expectation correct?
- Look for mock/stub issues: are dependencies configured correctly?
- Check parameter values: what inputs were passed to the function under test?
### 2. **Exception Failures**
Tests fail when PowerShell throws an exception instead of successful completion.
**Example:**
```
Command: Write-Host $null
Error: Cannot bind argument to parameter 'Object' because it is null.
```
**How to analyze:**
- Read the exception message: what operation failed?
- Check the stack trace: where in the test or tested code did it throw?
- Verify preconditions: does the test setup provide required values/mocks?
- Look for environmental issues: missing modules, permissions, file system state?
### 3. **Timeout Failures**
A test takes longer than the allowed timeout to complete.
**Example:**
```
Test 'Should complete in reasonable time' timed out after 30 seconds
```
**How to analyze:**
- Is the timeout appropriate for this test type? (network tests need more time)
- Is there an infinite loop in the test or tested code?
- Are there resource contention issues on the CI runner?
- Does the test hang waiting for something (file lock, network, process)?
### 4. **Skip/Ignored Reason Analysis**
Tests marked as skipped or ignored provide clues about test environment.
**Example:**
```
Test marked [Skip("Only runs on Windows")] - running on Linux
Test marked [Ignore("Known issue #12345")]
```
**How to analyze:**
- Read the skip/ignore reason: is it still valid?
- Check if environment has changed: platform, module versions, etc.
- Verify issue status: is the known issue still open? Has it been fixed?
- Determine if skip should be removed or if test needs environment changes
### 5. **Flaky/Intermittent Failures**
Tests that sometimes pass, sometimes fail indicate race conditions or environment sensitivity.
**Example:**
- Test passes locally but fails on CI
- Test passes first run of suite, fails on second run
- Test passes on Windows but fails on Linux
**How to analyze:**
- Look for timeout races: is timing involved in the test?
- Check for test isolation issues: does one test affect another?
- Verify environment differences: CI vs. local paths, permissions, versions
- Look for external dependencies: network calls, file I/O, process interactions
## Key Artifacts and Locations
| Item | Purpose | Location |
|------|---------|----------|
| Test result XML | Pester output with test cases, failures, errors | Workflow artifacts: `junit-pester-*.xml` |
| Job logs | Full job output including test execution and errors | GitHub Actions run logs or `gh run download` |
| Stack traces | Error location information from failed assertions | Within job logs and XML failure messages |
| Test files | The actual Pester test code (`.ps1` files) | `test/` directory in repository |
## Analysis Workflow
### ⚠️ Important: These Steps MUST Be Followed In Order
Each step depends on the previous one. Skipping or re-ordering steps causes incomplete analysis:
- **Step 1** (identify jobs) → You get the RUN_ID needed for Step 2
- **Step 2** (download) → You get the artifacts needed for Step 3
- **Step 3** (extract) → You discover what failures exist for Step 4
- **Step 4** (read messages) → You understand the errors to analyze in Step 5
- **Step 5** (context) → You gather information to make recommendations in Step 6
- **Step 6** (interpret) → You use all above to recommend fixes
**Real Problem We Had**:
- ❌ Jumped to Step 3 without Step 1-2
- ❌ Used random test data from context instead of downloading PR artifacts
- ❌ Skipped Steps 5-6 entirely
- ❌ Made recommendations without full context
**Result**: Wrong analysis and recommendations that didn't actually fix the problem.
### Recommended: Use the Automated Script
```powershell
./.github/skills/analyze-pester-failures/scripts/analyze-pr-test-failures.ps1 -PR <PR_NUMBER>
```
This enforces the workflow and prevents skipping.
### Step 2: Get Test Results
Fetch the test result artifacts and job logs:
```powershell
# Download artifacts including test XML results
gh run download <RUN_ID> --dir ./artifacts
# Get job logs
gh run view <RUN_ID> --log > test-logs.txt
# Inspect test XML
$xml = [xml](Get-Content ./artifacts/junit-pester-*.xml)
$xml.'test-results' | Select-Object total, failures, errors, ignored, inconclusive
```
### Step 3: Extract Specific Failures
Find the failing test cases in the XML:
```powershell
# Get all failed test cases
$xml = [xml](Get-Content ./artifacts/junit-pester-*.xml)
$failures = $xml.SelectNodes('.//test-case[@result = "Failure"]')
# For each failure, display key info
$failures | ForEach-Object {
[PSCustomObject]@{
Name = $_.name
Description = $_.description
Message = $_.failure.message
StackTrace = $_.failure.'stack-trace'
}
}
```
### Step 4: Read the Error Message
The error message tells you what went wrong:
**Assertion failures:**
```
Expected $true but got $false
Expected "value1" but got "value2"
Expression should have failed with exception, but didn't
```
**Exceptions:**
```
Cannot find a parameter with name 'Name'
Property 'Property' does not exist on 'Object'
Cannot bind argument to parameter because it is null
```
**Timeouts:**
```
Test timed out after 30 seconds
Test is taking too long to complete
```
### Step 5: Understand the Context
Look at the test file to understand what was being tested:
```powershell
# Find the test file mentioned in the stack trace
# Example: /path/to/test/Feature.Tests.ps1:42
# Read the test code around that line
code <test-file-path>:<line-number>
# Understand:
# - What assertion is on that line?
# - What is the test trying to verify?
# - What are the setup/mock/before conditions?
# - Are there recent changes to the function being tested?
```
### Step 6: Interpret the Failure
Determine the root cause category:
**Test issue (needs code fix):**
- Assertion logic is wrong
- Test expectations don't match actual behavior
- Test setup is incomplete
- Mock/stub configuration missing
**Environmental issue (needs environment change):**
- Test assumes a specific file or registry entry exists
- Test requires Windows/Linux specifically
- Test requires specific PowerShell version
- Test requires specific module version
- Timing-sensitive test affected by CI load
**Data issue (needs input data change):**
- Test data no longer valid
- External API changed format
- Configuration file has changed structure
**Flakiness (needs test hardening):**
- Race condition in test
- Timing assumptions too tight
- Resource contention on CI runner
- Non-deterministic behavior in tested code
## Common Test Failure Patterns
| Pattern | What It Means | Example | Next Step |
|---------|---------------|---------|-----------|
| `Expected $true but got $false` | Assertion on boolean result failed | Test expects function returns true, but it returns false | Check function logic for bug or test logic for wrong expectation |
| `Cannot find path` | File or directory doesn't exist | Test tries to read config file that's not present | Verify file path, check test setup, ensure CI environment has file |
| `Cannot bind argument to parameter 'X'` | Required parameter value is null or wrong type | Function called with $null where object expected | Check test mock setup, verify parameter types |
| `Test timed out after X seconds` | Test exceeded time limit | Network call or loop takes too long | Increase timeout for slow test, find infinite loop, mock network calls |
| `Expression should have failed but didn't` | Exception wasn't thrown when expected | Test expects error but function succeeds | Check if function behavior changed, update test expectation |
| `Could not find parameter 'X'` | Function doesn't have parameter | Test calls function with parameter that doesn't exist | Check PowerShell version, verify function signature, update test |
| `This platform is not supported` | Test skipped on current OS | Windows-only test running on Linux | Add platform check, update test environment, or mark as platform-specific |
| `Test marked [Ignore]` | Test explicitly disabled | Test has `[Ignore("reason")]` attribute | Check if reason still valid, remove if issue fixed |
## Interpreting Test Results
### Test Result Counts
Pester test outcomes are categorized as:
| Count | Meaning | Notes |
|-------|---------|-------|
| `total` | Total number of test cases executed | Should match: passed + failed + errors + skipped + ignored |
| `failures` | Test assertions that failed | `Expected X but got Y` type failures |
| `errors` | Tests that threw exceptions | Unhandled PowerShell exceptions during test |
| `skipped` | Tests explicitly skipped (marked with `-Skip`) | Test code recognizes condition and skips |
| `ignored` | Tests marked as ignored (marked with `-Ignore`) | Test disabled intentionally, usually notes reason |
| `inconclusive` | Tests with unclear result | Rare; usually means test framework issue |
| `passed` | Tests with passing assertions | `total - failures - errors - skipped - ignored` |
### Stack Trace Interpretation
A stack trace shows where the failure occurred:
```
at /home/runner/work/PowerShell/test/Feature.Tests.ps1:42
Means:
- File: /home/runner/work/PowerShell/test/Feature.Tests.ps1
- Line: 42
- Look at that line to see which assertion failed
```
### Understanding Skipped Tests
When XML shows `result="Ignored"` or `result="Skipped"`:
```xml
<test-case name="Test Name" result="Ignored">
<reason>Only runs on Windows</reason>
</test-case>
```
The reason explains why test didn't run. Not a failure, but important for understanding test coverage.
## Providing Test Failure Analysis
### Investigation Questions
After gathering test output, ask yourself:
1. **Is the test code correct?**
- Does the test assertion match the expected behavior?
- Are test expectations still valid?
- Has the function being tested changed?
2. **Is the test setup correct?**
- Are mocks/stubs configured properly?
- Does the test environment have required files/configuration?
- Are preconditions (database, files, services) met?
3. **Is this a code bug or test issue?**
- Does the tested function have a logic error?
- Or does the test have incorrect expectations?
4. **Is this environment-specific?**
- Only fails on Windows/Linux?
- Only fails on CI but passes locally?
- Timing-dependent or resource-dependent?
5. **Is this a known/expected failure?**
- Is there already an issue tracking this failure?
- Is the test marked as flaky or expected to fail?
- Does the skip/ignore reason still apply?
### Recommendation Framework
Based on your analysis:
| Finding | Recommendation |
|---------|-----------------|
| Test logic is wrong | "Test assertion on line X is incorrect. Test expects Y but function correctly returns Z. Update test expectation." |
| Tested code has bug | "Function at file.ps1#L42 has logic error. When X happens, returns Y instead of Z. Fix the condition." |
| Missing test setup | "Test setup incomplete. Mock for dependency Y is not configured. Add `Mock Get-Y -MockWith { ... }`" |
| Environment issue | "Test is Windows-specific but running on Linux. Either add platform check or skip on non-Windows." |
| Flaky test | "Test is timing-sensitive (sleep 1 second). Increase timeout or use better synchronization." |
| Test should be skipped | "Test is marked Ignored for good reason. Keep it disabled until issue #12345 is fixed." |
### Tone and Structure
Provide analysis as:
1. **Summary** (1 sentence): What test is failing and general category
2. **Failure Details** (2-3 sentences): What the test output says
3. **Root Cause** (1-2 sentences): Why it's failing (test bug vs. code bug vs. environment)
4. **Recommendation** (actionable): What should be done to fix it
5. **Context** (optional): Link to related code, issues, or recent changes
## Examples
### Example 1: Assertion Failure Due to Code Bug
**Test Output:**
```
Expected 5 but got 3 at /path/to/Test.ps1:42
```
**Investigation:**
1. Look at line 42: `$result | Should -Be 5`
2. Check the test: It expects function to return 5 items
3. Check the function: It returns `$items | Where-Object {$_.Status -eq "Active"}` but the filter is wrong
4. Root cause: Function has logic error, not test error
**Recommendation:**
```
Test failure is due to a code bug:
The test Set-Configuration should return 5 items but returns 3.
Looking at the tested function at [module.ps1#L42](module.ps1#L42):
$activeItems = $items | Where-Object {$_.Status -eq "Active"}
The issue is the filter condition. It's currently filtering by "Active" status,
but should include "Pending" status as well.
Fix: Change line 42 to:
$activeItems = $items | Where-Object {$_.Status -ne "Disabled"}
Then re-run the test to verify it now returns 5 items as expected.
```
### Example 2: Test Setup Issue
**Test Output:**
```
Cannot find path '/expected/config.json' because it does not exist at /path/to/Test.ps1:15
```
**Investigation:**
1. Line 15 tries to read a config file
2. The test setup doesn't create this file
3. Works locally but fails on CI because CI doesn't have the same file
**Recommendation:**
```
Test setup is incomplete:
The test Initialize-Config fails because it expects /expected/config.json but the test doesn't create this file.
The test needs to ensure the config file exists. Currently line 12-14 doesn't set up the file:
# Before:
# (no setup of config file)
# After:
@{ setting1 = "value1"; setting2 = "value2" } | ConvertTo-Json |
Out-File $testConfigPath
Alternatively, the test function should accept a parameter for the config path and use a temporary file:
param([string]$ConfigPath = (New-TemporaryFile))
Re-run the test to verify the config file is properly available.
```
### Example 3: Platform-Specific Test Failure
**Test Output:**
```
Test 'should read Windows Registry' failed on Linux runner
Cannot find path 'HKEY_LOCAL_MACHINE:\...'
```
**Investigation:**
1. Test assumes Windows Registry exists (Windows-only)
2. Running on Linux runner doesn't have Registry
3. Test should skip on non-Windows platforms
**Recommendation:**
```
Test is platform-specific but running on wrong platform:
The test "should read Windows Registry" assumes Windows Registry exists but is running on Linux.
Add a platform check to skip this test on non-Windows systems:
It "should read Windows Registry" -Skip:$(-not $IsWindows) {
# test code here
}
Or group Windows-only tests in a separate Describe block with platform check:
Describe "Windows Registry Tests" -Skip:$(-not $IsWindows) {
# all Windows-specific tests here
}
This allows the test to be skipped on Linux/Mac while still running on Windows CI.
```
## References
- [Pester Testing Framework](https://pester.dev/) — Official documentation, best practices for test writing
- [Test Files](../../../test/) — PowerShell test suite in repository
- [GitHub Actions Documentation](https://docs.github.com/en/actions) — Understanding workflow runs and logs
- [PowerShell Documentation](https://learn.microsoft.com/en-us/powershell/) — Language reference for understanding test code
## Tips
1. **Read the error message first:** The error message is usually the most direct clue to the problem
2. **Check test vs. code blame:** Is the test wrong or is the code wrong? Look at both sides
3. **Verify test isolation:** Does one test failure affect others? Check for shared state or test ordering dependencies
4. **Test locally first:** Try running the failing test locally to reproduce and understand it better
5. **Check for environmental assumptions:** Windows-specific paths, module versions, file locations may differ on CI
6. **Look for skip/ignore patterns:** If a test is consistently ignored, check if the reason is still valid
7. **Compare passing vs. failing:** If test passes locally but fails on CI, the difference is usually environment-related
8. **Check recent changes:** Did a recent PR change the tested code or test itself?
9. **Understand Pester output format:** Different Pester versions, different `-ErrorAction`, `-WarningAction` produce different test results
10. **Don't assume CI is wrong:** Failures on CI often reveal real issues that local testing missed (network, file permissions, parallelization, etc.)
## Additional Links
- [PowerShell Repository](https://github.com/PowerShell/PowerShell)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Pester Testing Framework](https://github.com/Pester/Pester)
@@ -0,0 +1,163 @@
# Understanding Pester Test Failures
This reference explains how to interpret Pester test output and understand failure messages.
## Supported Formats
### Pester 4 Format
```
at line: 123 in C:\path\to\file.ps1
```
**Regex Pattern:**
```powershell
if ($StackTraceString -match 'at line:\s*(\d+)\s+in\s+(.+?)(?:\r|\n|$)') {
$result.Line = $matches[1]
$result.File = $matches[2].Trim()
return $result
}
```
### Pester 5 Format (Common)
```
at 1 | Should -Be 2, C:\path\to\file.ps1:123
at 1 | Should -Be 2, /home/runner/work/PowerShell/PowerShell/test/file.ps1:123
```
**Regex Pattern:**
```powershell
if ($StackTraceString -match ',\s*((?:[A-Za-z]:)?[\/\\].+?\.ps[m]?1):(\d+)') {
$result.File = $matches[1].Trim()
$result.Line = $matches[2]
return $result
}
```
### Alternative Format
```
at C:\path\to\file.ps1:123
at /path/to/file.ps1:123
```
**Regex Pattern:**
```powershell
if ($StackTraceString -match 'at\s+((?:[A-Za-z]:)?[\/\\][^,]+?\.ps[m]?1):(\d+)(?:\r|\n|$)') {
$result.File = $matches[1].Trim()
$result.Line = $matches[2]
return $result
}
```
## Troubleshooting Parsing Failures
### Issue: Line Number Extracted But File Path Is Null
**Cause:** Stack trace matches line-with-path pattern but file extraction doesn't work
**Solution:**
1. Check if file path exists as expected in filesystem
2. Verify regex doesn't have too-greedy bounds (check use of `.+?` vs `.+`)
3. Test regex against actual stack trace string:
```powershell
$trace = "at line: 42 in C:\path\to\test.ps1"
if ($trace -match 'at line:\s*(\d+)\s+in\s+(.+?)(?:\r|\n|$)') {
Write-Host "File: $($matches[2])" # Should be "C:\path\to\test.ps1"
}
```
### Issue: Special Characters in File Path Break Regex
**Cause:** Characters like parens `()`, brackets `[]`, pipes `|` have special meaning in regex
**Solution:**
1. Escape special chars in regex: `[Regex]::Escape($path)`
2. Use character class `[\/\\]` instead of alternation for path separators
3. Test with files containing problematic names:
```powershell
$traces = @(
"at line: 1 in C:\path\(with)\parens\test.ps1",
"at /home/user/[brackets]/test.ps1:5",
"at C:\path\with spaces\test.ps1:10"
)
# Test each against all patterns
```
### Issue: Regex Matches But Extracts Wrong Values
**Symptom:** $matches[1] is file instead of line, or vice versa
**Debug Steps:**
1. Print all captured groups: `$matches.Values | Format-Table -AutoSize`
2. Verify group order in regex matches expectations
3. Test with sample Pester output:
```powershell
$sampleTrace = @"
at 1 | Should -Be 2, /home/runner/work/PowerShell/test/file.ps1:42
"@
if ($sampleTrace -match ',\s*((?:[A-Za-z]:)?[\/\\].+?\.ps[m]?1):(\d+)') {
Write-Host "Match 1: $($matches[1])" # Should be file path
Write-Host "Match 2: $($matches[2])" # Should be line number
}
```
## Testing the Parser
Use this PowerShell script to validate `Get-PesterFailureFileInfo`:
```powershell
# Import the function
. ./build.psm1
$testCases = @(
@{
Input = "at line: 42 in C:\path\to\test.ps1"
Expected = @{ File = "C:\path\to\test.ps1"; Line = "42" }
},
@{
Input = "at /home/runner/work/test.ps1:123"
Expected = @{ File = "/home/runner/work/test.ps1"; Line = "123" }
},
@{
Input = "at 1 | Should -Be 2, /path/to/file.ps1:99"
Expected = @{ File = "/path/to/file.ps1"; Line = "99" }
}
)
foreach ($test in $testCases) {
$result = Get-PesterFailureFileInfo -StackTraceString $test.Input
$fileMatch = $result.File -eq $test.Expected.File
$lineMatch = $result.Line -eq $test.Expected.Line
$status = if ($fileMatch -and $lineMatch) { "✓ PASS" } else { "✗ FAIL" }
Write-Host "$status : $($test.Input)"
if (-not $fileMatch) { Write-Host " Expected file: $($test.Expected.File), got: $($result.File)" }
if (-not $lineMatch) { Write-Host " Expected line: $($test.Expected.Line), got: $($result.Line)" }
}
```
## Adding Support for New Formats
When Pester changes its output format:
1. **Capture sample output** from failing tests
2. **Identify the pattern** (e.g., "file path always after comma followed by colon")
3. **Write regex** to match pattern without over-matching
4. **Add to `Get-PesterFailureFileInfo`** before existing patterns (order matters for fallback)
5. **Test with samples** containing special characters, long paths, and edge cases
Example: Adding a new format at the top of the function:
```powershell
# Try pattern: "at <description>, <path>:<line>" (Pester 5.1 hypothetical)
if ($StackTraceString -match 'at .+?, ((?:[A-Za-z]:)?[\/\\].+?\.ps[m]?1):(\d+)') {
$result.File = $matches[1].Trim()
$result.Line = $matches[2]
return $result
}
# Try existing patterns...
```
Place new patterns **first** so they take precedence over fallback patterns.
@@ -0,0 +1,456 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
<#
.SYNOPSIS
Automated Pester test failure analysis workflow for GitHub PRs.
.DESCRIPTION
This script automates the complete analysis workflow defined in the analyze-pester-failures
skill. It performs all steps in order:
1. Identify failing test jobs in the PR
2. Download test artifacts and logs
3. Extract specific test failures
4. Parse error messages
5. Search logs for error markers and generate recommendations
By automating the workflow, this ensures analysis steps are followed in order
and nothing is skipped.
.PARAMETER PR
The GitHub PR number to analyze (e.g., 26800)
.PARAMETER Owner
Repository owner (default: PowerShell)
.PARAMETER Repo
Repository name (default: PowerShell)
.PARAMETER OutputDir
Directory to store analysis results (default: ./pester-analysis-PR<number>)
.PARAMETER Interactive
Prompt for recommendations after analysis (default: non-interactive)
.PARAMETER ForceDownload
Force re-download of artifacts and logs, even if they already exist
.EXAMPLE
.\.github\skills\analyze-pester-failures\scripts\analyze-pr-test-failures.ps1 -PR 26800
Analyzes PR #26800 and saves results to ./pester-analysis-PR26800
.EXAMPLE
.\.github\skills\analyze-pester-failures\scripts\analyze-pr-test-failures.ps1 -PR 26800 -Interactive
Interactive mode: shows failures and prompts for next steps
.EXAMPLE
.\.github\skills\analyze-pester-failures\scripts\analyze-pr-test-failures.ps1 -PR 26800 -ForceDownload
Re-download all logs and artifacts, skipping the cache
.NOTES
Requires: GitHub CLI (gh) configured and authenticated
This script enforces the workflow defined in .github/skills/analyze-pester-failures/SKILL.md
#>
param(
[Parameter(Mandatory)]
[int]$PR,
[string]$Owner = 'PowerShell',
[string]$Repo = 'PowerShell',
[string]$OutputDir,
[switch]$Interactive,
[switch]$ForceDownload
)
$ErrorActionPreference = 'Stop'
if (-not $OutputDir) {
$OutputDir = "./pester-analysis-PR$PR"
}
# Colors for output
$colors = @{
Step = [ConsoleColor]::Cyan
Success = [ConsoleColor]::Green
Warning = [ConsoleColor]::Yellow
Error = [ConsoleColor]::Red
Info = [ConsoleColor]::Gray
}
function Write-Step {
param([string]$text, [int]$number)
Write-Host "`n[$number/6] $text" -ForegroundColor $colors.Step -BackgroundColor Black
}
function Write-Result {
param([string]$text, [ValidateSet('Success','Warning','Error','Info')]$type = 'Info')
Write-Host $text -ForegroundColor $colors[$type]
}
Write-Host "`n=== Pester Test Failure Analysis ===" -ForegroundColor $colors.Step
Write-Host "PR: $Owner/$Repo#$PR" -ForegroundColor $colors.Info
Write-Host "Output Directory: $OutputDir" -ForegroundColor $colors.Info
# Ensure output directory exists
if (-not (Test-Path $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
}
# STEP 1: Identify the Failing Test Job
Write-Step "Identify failing test jobs" 1
Write-Result "Fetching PR status checks..." Info
$prResponse = gh pr view $PR --repo "$Owner/$Repo" --json 'statusCheckRollup' | ConvertFrom-Json
$allChecks = $prResponse.statusCheckRollup
$failedJobs = $allChecks | Where-Object { $_.conclusion -eq 'FAILURE' }
if (-not $failedJobs) {
Write-Result "✓ No failed jobs found" Success
Write-Host " Total checks: $($allChecks.Count)"
$allChecks | Where-Object { $_ } | ForEach-Object {
Write-Host " - $($_.name): $($_.conclusion)" -ForegroundColor $colors.Info
}
exit 0
}
Write-Result "✓ Found $($failedJobs.Count) failing job(s)" Warning
$failedJobs | Where-Object { $_.conclusion -eq 'FAILURE' } | ForEach-Object {
Write-Host " ✗ $($_.name) - $($_.conclusion)" -ForegroundColor $colors.Error
if ($_.detailsUrl) {
Write-Host " URL: $($_.detailsUrl)" -ForegroundColor $colors.Info
}
}
if ($Interactive) {
Write-Host "`nPress Enter to continue to Step 2..."
Read-Host | Out-Null
}
# STEP 2: Get Test Results
Write-Step "Download test artifacts and logs" 2
# Extract unique run IDs from failing jobs
$uniqueRuns = @()
foreach ($failedJob in $failedJobs) {
if ($failedJob.detailsUrl -match 'runs/(\d+)') {
$runId = $matches[1]
if ($runId -notin $uniqueRuns) {
$uniqueRuns += $runId
}
}
}
if ($uniqueRuns.Count -eq 0) {
Write-Result "✗ Could not extract run IDs from failing jobs" Error
exit 1
}
Write-Result "Found $($uniqueRuns.Count) run(s): $($uniqueRuns -join ', ')" Info
$artifactDir = Join-Path $OutputDir artifacts
# Check if artifacts already exist
$existingArtifacts = Get-ChildItem $artifactDir -Recurse -File -ErrorAction SilentlyContinue
if ($existingArtifacts -and -not $ForceDownload) {
Write-Result "✓ Artifacts already downloaded" Success
$existingArtifacts | ForEach-Object {
Write-Host " - $($_.FullName)" -ForegroundColor $colors.Info
}
} else {
Write-Result "Downloading artifacts from run $($uniqueRuns[0])..." Info
gh run download $uniqueRuns[0] --dir $artifactDir --repo "$Owner/$Repo" 2>&1 | Out-Null
if (Test-Path $artifactDir) {
Write-Result "✓ Artifacts downloaded" Success
Get-ChildItem $artifactDir -Recurse -File | ForEach-Object {
Write-Host " - $($_.FullName)" -ForegroundColor $colors.Info
}
} else {
Write-Result "✗ Failed to download artifacts" Error
exit 1
}
}
# Download individual job logs for failing jobs
Write-Result "Downloading individual job logs..." Info
$logsDir = Join-Path $OutputDir "logs"
if (-not (Test-Path $logsDir)) {
New-Item -ItemType Directory -Path $logsDir -Force | Out-Null
}
# Check if logs already exist
$existingLogs = Get-ChildItem $logsDir -Filter "*.txt" -ErrorAction SilentlyContinue
if ($existingLogs -and -not $ForceDownload) {
Write-Result "✓ Job logs already downloaded" Success
$existingLogs | ForEach-Object {
Write-Host " - $($_.Name)" -ForegroundColor $colors.Info
}
} else {
# Process each run and get its jobs
$failedJobIds = @()
foreach ($runId in $uniqueRuns) {
$runJobs = gh run view $runId --repo "$Owner/$Repo" --json jobs | ConvertFrom-Json
foreach ($failedJob in $failedJobs) {
# Check if this failed job belongs to this run
if ($failedJob.detailsUrl -match "runs/$runId/") {
$jobMatch = $runJobs.jobs | Where-Object { $_.name -eq $failedJob.name } | Select-Object -First 1
if ($jobMatch) {
$failedJobIds += @{
name = $failedJob.name
id = $jobMatch.databaseId
runId = $runId
}
}
}
}
}
# Download logs for all failed jobs
foreach ($jobInfo in $failedJobIds) {
$logFile = Join-Path $logsDir ("log-{0}.txt" -f ($jobInfo.name -replace '[^a-zA-Z0-9-]', '_'))
Write-Result " Downloading: $($jobInfo.name) (Run $($jobInfo.runId))" Info
gh run view $jobInfo.runId --log --job $jobInfo.id --repo "$Owner/$Repo" > $logFile 2>&1
}
Write-Result "✓ Job logs downloaded" Success
Get-ChildItem $logsDir -Filter "*.txt" | ForEach-Object {
Write-Host " - $($_.Name)" -ForegroundColor $colors.Info
}
}
if ($Interactive) {
Write-Host "`nPress Enter to continue to Step 3..."
Read-Host | Out-Null
}
# STEP 3: Extract Specific Failures
Write-Step "Extract test failures from XML" 3
$xmlFiles = Get-ChildItem $artifactDir -Filter "*.xml" -Recurse
if (-not $xmlFiles) {
Write-Result "✗ No test result XML files found" Error
exit 1
}
Write-Result "✓ Found $($xmlFiles.Count) test result file(s)" Success
$allFailures = @()
foreach ($xmlFile in $xmlFiles) {
Write-Result "`nParsing: $($xmlFile.Name)" Info
try {
[xml]$xml = Get-Content $xmlFile
$testResults = $xml.'test-results'
Write-Host " Total: $($testResults.total)" -ForegroundColor $colors.Info
Write-Host " Passed: $($testResults.passed)" -ForegroundColor $colors.Success
if ($testResults.failures -gt 0) {
Write-Host " Failed: $($testResults.failures)" -ForegroundColor $colors.Error
}
if ($testResults.errors -gt 0) {
Write-Host " Errors: $($testResults.errors)" -ForegroundColor $colors.Error
}
if ($testResults.skipped -gt 0) {
Write-Host " Skipped: $($testResults.skipped)" -ForegroundColor $colors.Warning
}
if ($testResults.ignored -gt 0) {
Write-Host " Ignored: $($testResults.ignored)" -ForegroundColor $colors.Warning
}
# Extract failures
$failures = $xml.SelectNodes('.//test-case[@result = "Failure"]')
foreach ($failure in $failures) {
$allFailures += @{
Name = $failure.name
File = $xmlFile.Name
Message = $failure.failure.message
StackTrace = $failure.failure.'stack-trace'
}
}
} catch {
Write-Result "✗ Error parsing XML: $_" Error
}
}
Write-Result "`n✓ Extracted $($allFailures.Count) failures total" Success
# Save failures to JSON for later analysis
$allFailures | ConvertTo-Json -Depth 10 | Out-File (Join-Path $OutputDir "failures.json")
if ($Interactive) {
Write-Host "`nPress Enter to continue to Step 4..."
Read-Host | Out-Null
}
# STEP 4: Read Error Messages
Write-Step "Analyze error messages" 4
$failuresByType = @{}
foreach ($failure in $allFailures) {
$message = $failure.Message -split "`n" | Select-Object -First 1
# Categorize failure
$type = 'Other'
if ($message -match 'Expected .* but got') { $type = 'Assertion' }
elseif ($message -match 'Cannot (find|bind)') { $type = 'Exception' }
elseif ($message -match 'timed out') { $type = 'Timeout' }
if (-not $failuresByType[$type]) {
$failuresByType[$type] = @()
}
$failuresByType[$type] += $failure
}
Write-Result "Failure breakdown:" Info
$failuresByType.GetEnumerator() | ForEach-Object {
Write-Host " $($_.Key): $($_.Value.Count)" -ForegroundColor $colors.Warning
}
Write-Result "`nTop failure messages:" Info
$allFailures | Group-Object Message | Sort-Object Count -Descending | Select-Object -First 3 | ForEach-Object {
Write-Host " [$($_.Count)x] $($_.Name -split "`n" | Select-Object -First 1)" -ForegroundColor $colors.Info
}
# Save analysis
$analysis = @{
FailuresByType = @{}
TopMessages = @()
}
$failuresByType.GetEnumerator() | ForEach-Object {
$analysis.FailuresByType[$_.Key] = $_.Value.Count
}
$allFailures | Group-Object Message | Sort-Object Count -Descending | Select-Object -First 5 | ForEach-Object {
$analysis.TopMessages += @{
Count = $_.Count
Message = ($_.Name -split "`n" | Select-Object -First 1)
}
}
$analysis | ConvertTo-Json | Out-File (Join-Path $OutputDir "analysis.json")
if ($Interactive) {
Write-Host "`nPress Enter to continue to Step 5..."
Read-Host | Out-Null
}
# STEP 5: Search Logs for Error Markers
Write-Step "Search logs for error markers" 5
$logsDir = Join-Path $OutputDir "logs"
if (-not (Test-Path $logsDir)) {
Write-Result "⚠ Logs directory not found" Warning
} else {
$logFiles = Get-ChildItem $logsDir -Filter "*.txt" -ErrorAction SilentlyContinue
if (-not $logFiles) {
Write-Result "⚠ No log files found in logs directory" Warning
} else {
Write-Result "Searching $($logFiles.Count) job log(s) for error markers ([-])" Info
Write-Result "Format: [JobName] [LineNumber] Content" Info
Write-Host ""
$allErrorLines = @()
foreach ($logFile in $logFiles) {
$jobName = $logFile.BaseName -replace '^log-', ''
$logLines = @(Get-Content $logFile)
for ($i = 0; $i -lt $logLines.Count; $i++) {
$line = $logLines[$i]
if ($line -match '\s\[-\]\s') {
$allErrorLines += @{
JobName = $jobName
LineNumber = $i + 1
Content = $line
}
}
}
}
if ($allErrorLines.Count -gt 0) {
Write-Result "✓ Found $($allErrorLines.Count) error marker line(s)" Warning
$allErrorLines | ForEach-Object {
Write-Host " [$($_.JobName)] [$($_.LineNumber)] $($_.Content)" -ForegroundColor $colors.Error
}
# Save to file
$allErrorLines | ConvertTo-Json | Out-File (Join-Path $OutputDir "error-markers.json")
Write-Result "✓ Error markers saved to error-markers.json" Success
} else {
Write-Result "✓ No error markers found in logs" Success
}
}
}
if ($Interactive) {
Write-Host "`nPress Enter to continue to Step 6..."
Read-Host | Out-Null
}
# STEP 6: Generate Recommendations
Write-Step "Generate recommendations" 6
$recommendations = @()
# Analyze patterns
if ($failuresByType['Assertion']) {
$recommendations += "Multiple assertion failures detected. These indicate test expectations don't match actual behavior."
}
if ($failuresByType['Exception']) {
$recommendations += "Exception errors found. Check test setup and prerequisites - may indicate missing files, modules, or permissions."
}
if ($failuresByType['Timeout']) {
$recommendations += "Timeout failures suggest slow or hanging operations. Consider network issues or resource constraints on CI."
}
# Check for patterns in failure messages
$failureMessages = $allFailures.Message -join "`n"
if ($failureMessages -match 'PackageManagement') {
$recommendations += "PackageManagement module issues detected. Verify module availability and help repository access."
}
if ($failureMessages -match 'Update-Help') {
$recommendations += "Update-Help failures detected. Check network connectivity to help repository and help installation paths."
}
Write-Result "`n📋 Recommendations:" Info
if ($recommendations) {
$recommendations | ForEach-Object { Write-Host " • $_" -ForegroundColor $colors.Info }
} else {
Write-Host " • Review failures in detail" -ForegroundColor $colors.Info
Write-Host " • Check if test changes are needed" -ForegroundColor $colors.Info
Write-Host " • Consider environment-specific issues" -ForegroundColor $colors.Info
}
$recommendations | Out-File (Join-Path $OutputDir "recommendations.txt")
# Summary
Write-Host "`n=== Analysis Complete ===" -ForegroundColor $colors.Step
Write-Host "Results saved to: $OutputDir" -ForegroundColor $colors.Info
Write-Host " - failures.json (detailed failure data)" -ForegroundColor $colors.Info
Write-Host " - analysis.json (summary analysis)" -ForegroundColor $colors.Info
Write-Host " - recommendations.txt (suggested fixes)" -ForegroundColor $colors.Info
Write-Host " - error-markers.json (error markers from logs)" -ForegroundColor $colors.Info
Write-Host " - logs/ (individual job log files)" -ForegroundColor $colors.Info
Write-Host " - artifacts/ (downloaded test artifacts)" -ForegroundColor $colors.Info
Write-Host "`nNext steps:" -ForegroundColor $colors.Step
Write-Host "1. Review recommendations.txt for analysis" -ForegroundColor $colors.Info
Write-Host "2. Examine failures.json for detailed error messages" -ForegroundColor $colors.Info
Write-Host "3. Check error-markers.json for specific test failures in logs" -ForegroundColor $colors.Info
Write-Host "4. Review individual job logs in logs/ directory for contextual details" -ForegroundColor $colors.Info
Write-Host "`n"
+4 -4
View File
@@ -37,17 +37,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: '0'
- uses: actions/setup-dotnet@v5
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: ./global.json
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v3.29.5
uses: github/codeql-action/init@1c5b675653bb5c22dbe9b12b556ec555138e09fd
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -74,4 +74,4 @@ jobs:
shell: pwsh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v3.29.5
uses: github/codeql-action/analyze@1c5b675653bb5c22dbe9b12b556ec555138e09fd
+4 -1
View File
@@ -10,6 +10,9 @@ on:
paths:
- ".github/workflows/copilot-setup-steps.yml"
permissions:
contents: read
jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
# See https://docs.github.com/en/copilot/customizing-copilot/customizing-the-development-environment-for-copilot-coding-agent
@@ -22,7 +25,7 @@ jobs:
# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
+2 -2
View File
@@ -17,6 +17,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: 'Dependency Review'
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
+2 -2
View File
@@ -18,11 +18,11 @@ jobs:
steps:
- name: Check out the repository
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Verify PR has label starting with 'cl-'
id: verify-labels
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const labels = context.payload.pull_request.labels.map(label => label.name.toLowerCase());
+12 -10
View File
@@ -10,6 +10,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
paths:
- "**"
- "*"
@@ -23,6 +24,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
- "*-feature"
# Path filters for PRs need to go into the changes job
@@ -57,7 +59,7 @@ jobs:
packagingChanged: ${{ steps.filter.outputs.packagingChanged }}
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -76,7 +78,7 @@ jobs:
contents: read
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check for merge conflict markers
uses: "./.github/actions/infrastructure/merge-conflict-checker"
@@ -88,7 +90,7 @@ jobs:
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
@@ -103,7 +105,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Linux Unelevated CI
@@ -121,7 +123,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Linux Elevated CI
@@ -139,7 +141,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Linux Unelevated Others
@@ -157,7 +159,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Linux Elevated Others
@@ -181,7 +183,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1
@@ -244,7 +246,7 @@ jobs:
- infrastructure_tests
# - analyze
if: always()
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@v1.0.0
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@c8b3ad5819ad7078f3e375519b4f8c6232d1cbdf # v1.0.0
with:
needs_context: ${{ toJson(needs) }}
linux_packaging:
@@ -255,7 +257,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Linux Packaging
+14 -11
View File
@@ -8,6 +8,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
paths:
- "**"
- "*"
@@ -21,6 +22,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
- "*-feature"
# Path filters for PRs need to go into the changes job
@@ -54,9 +56,10 @@ jobs:
outputs:
source: ${{ steps.filter.outputs.source }}
buildModuleChanged: ${{ steps.filter.outputs.buildModuleChanged }}
packagingChanged: ${{ steps.filter.outputs.packagingChanged }}
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Change Detection
id: filter
@@ -71,7 +74,7 @@ jobs:
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Build
@@ -85,7 +88,7 @@ jobs:
runs-on: macos-15-large
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: macOS Unelevated CI
@@ -103,7 +106,7 @@ jobs:
runs-on: macos-15-large
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: macOS Elevated CI
@@ -121,7 +124,7 @@ jobs:
runs-on: macos-15-large
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: macOS Unelevated Others
@@ -139,7 +142,7 @@ jobs:
runs-on: macos-15-large
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: macOS Elevated Others
@@ -161,15 +164,15 @@ jobs:
name: macOS packaging and testing
needs:
- changes
if: ${{ needs.changes.outputs.source == 'true' || needs.changes.outputs.buildModuleChanged == 'true' }}
if: ${{ needs.changes.outputs.packagingChanged == 'true' }}
runs-on:
- macos-15-large
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- uses: actions/setup-dotnet@v5
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: ./global.json
- name: Bootstrap packaging
@@ -228,7 +231,7 @@ jobs:
testResultsFolder: "${{ runner.workspace }}/testResults"
- name: Upload package artifact
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: macos-package
path: "*.pkg"
@@ -242,6 +245,6 @@ jobs:
- macos_test_unelevated_ci
- macos_test_unelevated_others
if: always()
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@v1.0.0
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@c8b3ad5819ad7078f3e375519b4f8c6232d1cbdf # v1.0.0
with:
needs_context: ${{ toJson(needs) }}
+3 -3
View File
@@ -32,7 +32,7 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
@@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v3.29.5
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v3.29.5
with:
sarif_file: results.sarif
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Verify markdown links
id: verify
+9 -7
View File
@@ -6,6 +6,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
paths:
- "**"
- "*"
@@ -20,6 +21,7 @@ on:
- master
- release/**
- github-mirror
- "servicing-*"
- "*-feature"
# Path filters for PRs need to go into the changes job
@@ -60,7 +62,7 @@ jobs:
packagingChanged: ${{ steps.filter.outputs.packagingChanged }}
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Change Detection
id: filter
@@ -75,7 +77,7 @@ jobs:
runs-on: windows-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Build
@@ -89,7 +91,7 @@ jobs:
runs-on: windows-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Windows Unelevated CI
@@ -107,7 +109,7 @@ jobs:
runs-on: windows-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Windows Elevated CI
@@ -125,7 +127,7 @@ jobs:
runs-on: windows-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Windows Unelevated Others
@@ -143,7 +145,7 @@ jobs:
runs-on: windows-latest
steps:
- name: checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Windows Elevated Others
@@ -189,6 +191,6 @@ jobs:
- analyze
- windows_packaging
if: always()
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@v1.0.0
uses: PowerShell/compliance/.github/workflows/ready-to-merge.yml@c8b3ad5819ad7078f3e375519b4f8c6232d1cbdf # v1.0.0
with:
needs_context: ${{ toJson(needs) }}
@@ -13,6 +13,9 @@ env:
SYSTEM_ARTIFACTSDIRECTORY: ${{ github.workspace }}/artifacts
BUILD_ARTIFACTSTAGINGDIRECTORY: ${{ github.workspace }}/artifacts
permissions:
contents: read
jobs:
package:
name: ${{ matrix.architecture }} - ${{ matrix.channel }}
@@ -36,7 +39,7 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
@@ -61,7 +64,7 @@ jobs:
shell: pwsh
- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: ./global.json
@@ -81,7 +84,7 @@ jobs:
- name: Upload Build Artifacts
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: windows-packaging-${{ matrix.architecture }}-${{ matrix.channel }}
path: |
+6 -3
View File
@@ -14,18 +14,21 @@ on:
required: false
default: testResults-xunit
permissions:
contents: read
jobs:
xunit:
name: Run xUnit Tests
runs-on: ${{ inputs.runner_os }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 1000
- name: Setup .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: ./global.json
@@ -46,7 +49,7 @@ jobs:
Write-Host "Completed xUnit test run."
- name: Upload xUnit results
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: ${{ inputs.test_results_artifact_name }}
+3
View File
@@ -119,5 +119,8 @@ assets/manpage/*.gz
tmp/*
.env.local
# Pester test failure analysis results (generated by analyze-pr-test-failures.ps1)
**/pester-analysis-*/
# Ignore CTRF report files
crtf/*
+4
View File
@@ -510,6 +510,10 @@ dotnet_diagnostic.CA1846.severity = warning
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1847
dotnet_diagnostic.CA1847.severity = warning
# CA1852: Seal internal types
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1852
dotnet_diagnostic.CA1852.severity = warning
# CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)'
# https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1853
dotnet_diagnostic.CA1853.severity = warning
@@ -64,7 +64,7 @@ function Get-MappedRepositoryIds {
$repoIds.AddRange(([string[]]$repos.id))
}
else {
Write-Failure "Could not find repo for $urlGlob"
throw "Could not find repo for $urlGlob"
}
if ($repoIds.Count -gt 0) {
+408 -76
View File
@@ -1,31 +1,88 @@
trigger: none
pr: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'createVPack'
displayName: 'Create and Submit VPack'
type: boolean
default: true
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: 'ReleaseTagVar'
type: string
displayName: 'Release Tag Var:'
default: 'fromBranch'
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: netiso
displayName: "Network Isolation Policy"
type: string
values:
- KS4
- R1
- Netlock
default: "R1"
- name: IsEarlyAccess
type: boolean
default: false
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net11'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: msixbundle_vPack_$(date:yyMM).$(date:dd)$(rev:rrr)
name: msixbundle_vPack_$(Build.SourceBranchName)_Prod.True_Create.${{ parameters.createVPack }}_$(date:yyyyMMdd).$(rev:rr)
variables:
CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)]
system.debug: ${{ parameters.debug }}
BuildSolution: $(Build.SourcesDirectory)\dirs.proj
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
BuildConfiguration: Release
WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest'
Codeql.Enabled: false # pipeline is not building artifacts; it repackages existing artifacts into a vpack
DOTNET_CLI_TELEMETRY_OPTOUT: 1
POWERSHELL_TELEMETRY_OPTOUT: 1
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)]
- name: system.debug
value: ${{ parameters.debug }}
- name: BuildSolution
value: $(Build.SourcesDirectory)\dirs.proj
- name: BuildConfiguration
value: Release
- name: WindowsContainerImage
value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest'
- name: Codeql.Enabled
value: false # pipeline is not building artifacts; it repackages existing artifacts into a vpack
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: 1
- name: POWERSHELL_TELEMETRY_OPTOUT
value: 1
- name: nugetMultiFeedWarnLevel
value: none
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
- name: netiso
value: ${{ parameters.netiso }}
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
- name: EARLY_ACCESS_FEED
value: ${{ parameters.EarlyAccessFeed }}
- name: DOTNET_RUNTIME_VERSION
value: ${{ parameters.DOTNET_RUNTIME_VERSION }}
- name: DOTNET_SDK_VERSION
value: ${{ parameters.DOTNET_SDK_VERSION }}
- group: certificate_logical_to_actual # used within signing task
- group: MSIXSigningProfile
- group: msixTools
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- group: DotNetPrivateBuildAccess
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
resources:
repositories:
@@ -34,24 +91,17 @@ resources:
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
pipelines:
- pipeline: PSPackagesOfficial
source: 'PowerShell-Packages-Official'
trigger:
branches:
include:
- master
- releases/*
extends:
template: v2/Microsoft.Official.yml@onebranchTemplates
parameters:
platform:
name: 'windows_undocked' # windows undocked
featureFlags:
WindowsHostVersion:
Version: 2022
Network: ${{ variables.netiso }}
cloudvault:
enabled: false
globalSdl:
useCustomPolicy: true # for signing code
disableLegacyManifest: true
@@ -75,71 +125,353 @@ extends:
tsaOptionsFile: .config/tsaoptions.json
stages:
- stage: build
- stage: prep
displayName: 'Prepare early access .NET'
dependsOn: []
jobs:
- job: main
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
parameters:
DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
- ${{ else }}:
- job: skip_download_dotnet_early_access
displayName: 'Skip early access .NET download'
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_signing_setup_enabled
value: false
- name: ob_sdl_codeSignValidation_enabled
value: false
steps:
- pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET download.'
- stage: Build_MSIX_Package
displayName: 'Build and create MSIX packages'
dependsOn: [prep]
jobs:
- job: Build
pool:
type: windows
strategy:
matrix:
x64:
Architecture: x64
arm64:
Architecture: arm64
variables:
ArtifactPlatform: 'windows'
ob_outputDirectory: '$(BUILD.SOURCESDIRECTORY)\out'
ob_createvpack_enabled: ${{ parameters.createVPack }}
ob_createvpack_packagename: 'PowerShell.app'
ob_createvpack_owneralias: 'dongbow'
ob_createvpack_description: 'VPack for the PowerShell Application'
ob_createvpack_targetDestinationDirectory: '$(Destination)'
ob_createvpack_propsFile: false
ob_createvpack_provData: true
ob_createvpack_metadata: '$(Build.SourceVersion)'
ob_createvpack_versionAs: string
ob_createvpack_version: '$(version)'
ob_createvpack_verbose: true
ob_artifactBaseName: drop_build_$(Architecture)
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
EARLY_ACCESS_FEED: ${{ parameters.EarlyAccessFeed }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
steps:
- template: .pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
- checkout: self
displayName: Checkout source code - during restore
clean: true
path: s ## $(Build.SourcesDirectory) is at '$(Pipeline.Workspace)\s', so we need to check out repo to the 's' folder.
env:
ob_restore_phase: true
- pwsh: |
Write-Verbose -Verbose 'PowerShell Version: $(version)'
if('$(version)' -match '-') {
throw "Don't release a preview build msixbundle package"
}
displayName: Stop any preview release
# The env variable 'ReleaseTagVar' will be updated in this step.
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: yes
- download: PSPackagesOfficial
artifact: 'drop_msixbundle_CreateMSIXBundle'
displayName: Download package
- pwsh: |
$releaseTag = '$(ReleaseTagVar)'
if ($releaseTag -match '-') {
throw "Never release msixbundle vpack for a preview build. Current version: $releaseTag"
}
- pwsh: |
$payloadDir = '$(Pipeline.Workspace)\PSPackagesOfficial\drop_msixbundle_CreateMSIXBundle'
Get-ChildItem $payloadDir -Recurse | Out-String -Width 150
$vstsCommandString = "vso[task.setvariable variable=PayloadDir]$payloadDir"
Write-Host "sending " + $vstsCommandString
Write-Host "##$vstsCommandString"
displayName: 'Capture Artifact Listing'
# Check if release tag matches the expected format v#.#.#
$matched = $releaseTag -match '^v\d+\.(\d+)\.\d+$'
if (-not $matched) {
throw "Release tag must be in the format v#.#.#, such as 'v7.4.3'. Current version: $releaseTag"
}
displayName: Stop any preview release
env:
ob_restore_phase: true
- pwsh: |
$bundlePackage = Get-ChildItem '$(PayloadDir)\*.msixbundle'
Write-Verbose -Verbose ("MSIX bundle package: " + $bundlePackage.FullName -join ', ')
if ($bundlePackage.Count -ne 1) {
throw "Expected to find 1 MSIX bundle package, but found $($bundlePackage.Count)"
### START BUILD ###
# Clone the checked out PowerShell repo to '/PowerShell' and set the variable 'PowerShellRoot'.
- template: /.pipelines/templates/cloneToOfficialPath.yml@self
- template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self
parameters:
repoRoot: $(PowerShellRoot)
# Add CodeQL Init task right before your 'Build' step.
- task: CodeQL3000Init@0
env:
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
inputs:
Enabled: true
# AnalyzeInPipeline: false = upload results
# AnalyzeInPipeline: true = do not upload results
AnalyzeInPipeline: false
Language: csharp
- template: /.pipelines/templates/install-dotnet.yml@self
- pwsh: |
$runtime = switch ($env:Architecture)
{
"x64" { "win7-x64" }
"arm64" { "win-arm64" }
}
if (-not (Test-Path '$(ob_outputDirectory)' -PathType Container)) {
$null = New-Item '$(ob_outputDirectory)' -ItemType Directory -ErrorAction Stop
$vstsCommandString = "vso[task.setvariable variable=Runtime]$runtime"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
Write-Verbose -Message "Building PowerShell with Runtime: $runtime for '$env:BuildConfiguration' configuration"
Import-Module -Name $(PowerShellRoot)/build.psm1 -Force
$buildWithSymbolsPath = New-Item -ItemType Directory -Path $(Pipeline.Workspace)/Symbols_$(Architecture) -Force
Start-PSBootstrap -Scenario Package
$null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose
Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath -Clean -PSModuleRestore -ReleaseTag $(ReleaseTagVar)
$refFolderPath = Join-Path $buildWithSymbolsPath 'ref'
Write-Verbose -Verbose "refFolderPath: $refFolderPath"
$outputPath = Join-Path '$(ob_outputDirectory)' 'psoptions'
$null = New-Item -ItemType Directory -Path $outputPath -Force
$psOptPath = "$outputPath/psoptions.json"
Save-PSOptions -PSOptionsPath $psOptPath
Write-Verbose -Verbose "Verifying pdbs exist in build folder"
$pdbs = Get-ChildItem -Path $buildWithSymbolsPath -Recurse -Filter *.pdb
if ($pdbs.Count -eq 0) {
throw "No pdbs found in build folder"
}
else {
Write-Verbose -Verbose "Found $($pdbs.Count) pdbs in build folder"
$pdbs | ForEach-Object {
Write-Verbose -Verbose "Pdb: $($_.FullName)"
}
$targetPath = Join-Path '$(ob_outputDirectory)' 'Microsoft.PowerShell_8wekyb3d8bbwe.msixbundle'
Copy-Item -Verbose -Path $bundlePackage.FullName -Destination $targetPath
displayName: 'Stage msixbundle for vpack'
$pdbs | Compress-Archive -DestinationPath '$(ob_outputDirectory)\symbols-$(Architecture).zip' -Update
}
- pwsh: |
Write-Verbose "VPack Version: $(ob_createvpack_version)" -Verbose
$vpackFiles = Get-ChildItem -Path $(ob_outputDirectory)\* -Recurse
if($vpackFiles.Count -eq 0) {
throw "No files found in $(ob_outputDirectory)"
}
$vpackFiles | Out-String -Width 150
displayName: Debug Output Directory and Version
condition: succeededOrFailed()
Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration"
displayName: 'Build Windows Universal - $(Architecture)-$(BuildConfiguration) Symbols folder'
env:
${{ if eq(parameters.IsEarlyAccess, true) }}:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
# Add CodeQL Finalize task right after your 'Build' step.
- task: CodeQL3000Finalize@0
env:
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
inputs:
sourceScanPath: '$(PowerShellRoot)\src'
ob_restore_phase: true
# The signed files will be put in '$(ob_outputDirectory)\Signed-$(Runtime)' after this step.
- template: /.pipelines/templates/obp-file-signing.yml@self
parameters:
binPath: '$(Pipeline.Workspace)/Symbols_$(Architecture)'
OfficialBuild: true
### END OF BUILD ###
- pwsh: |
Get-ChildItem -Path '$(ob_outputDirectory)\Signed-$(Runtime)' -Recurse | Out-String -Width 9999
displayName: Capture signed files
condition: succeededOrFailed()
- pwsh: |
Get-ChildItem -Path env: | Out-String -Width 9999
displayName: Capture Environment
condition: succeededOrFailed()
### START Packaging ###
- template: /.pipelines/templates/shouldSign.yml@self
parameters:
ob_restore_phase: false
- pwsh: |
Write-Verbose -Verbose "runtime = '$(Runtime)'"
Write-Verbose -Verbose "RepoRoot = '$(PowerShellRoot)'"
$runtime = '$(Runtime)'
$repoRoot = '$(PowerShellRoot)'
Import-Module "$repoRoot\build.psm1"
Import-Module "$repoRoot\tools\packaging"
Find-Dotnet
$signedFilesPath = '$(ob_outputDirectory)\Signed-$(Runtime)'
$psoptionsFilePath = '$(ob_outputDirectory)\psoptions\psoptions.json'
Write-Verbose -Verbose "signedFilesPath: $signedFilesPath"
Write-Verbose -Verbose "psoptionsFilePath: $psoptionsFilePath"
Write-Verbose -Message "checking pwsh exists in $signedFilesPath" -Verbose
if (-not (Test-Path $signedFilesPath\pwsh.exe)) {
throw "pwsh.exe not found in $signedFilesPath"
}
Write-Verbose -Message "Restoring PSOptions from $psoptionsFilePath" -Verbose
Restore-PSOptions -PSOptionsPath "$psoptionsFilePath"
Get-PSOptions | Write-Verbose -Verbose
$metadata = Get-Content "$repoRoot\tools\metadata.json" -Raw | ConvertFrom-Json
Write-Verbose -Verbose "metadata:"
$metadata | Out-String | Write-Verbose -Verbose
$publishLTS = $metadata.LTSRelease.PublishToChannels
$publishStable = $metadata.StableRelease.PublishToChannels
Write-Verbose -Verbose "Publish LTS: $publishLTS"
Write-Verbose -Verbose "Publish Stable: $publishStable"
if (-not $publishLTS -and -not $publishStable) {
throw "metadata.json indicates no channels to publish to."
}
## Generated packages are placed in the current directory by default.
Set-Location $repoRoot
Start-PSPackage -Type msix -SkipReleaseChecks -WindowsRuntime $runtime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$publishLTS
if ($publishLTS -and $publishStable) {
$enabledChannels = "LTS,Stable"
Write-Verbose -Verbose "Publish to both LTS and Stable channels. Building additional Stable MSIX."
Start-PSPackage -Type msix -SkipReleaseChecks -WindowsRuntime $runtime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath
}
$msixPkgNameFilter = "PowerShell*.msix"
$msixPkgFile = Get-ChildItem -Path $repoRoot -Filter $msixPkgNameFilter -Recurse -File | ForEach-Object FullName
Write-Verbose -Verbose "Unsigned msix package(s): $msixPkgFile"
$pkgDir = '$(ob_outputDirectory)\pkgs'
$null = New-Item -ItemType Directory -Path $pkgDir -Force
Copy-Item -Path $msixPkgFile -Destination $pkgDir -Force -Verbose
if (-not $enabledChannels) {
$enabledChannels = $publishLTS ? 'LTS' : ($publishStable ? 'Stable' : 'None')
}
## Create an output variable for the enabled channels so that downstream stages can use it.
$vstsCommandString = "vso[task.setvariable variable=EnabledChannels;isOutput=true]$enabledChannels"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
name: BuildMSIXPackage
displayName: 'Build MSIX Package (Unsigned)'
### END OF Packaging ###
- pwsh: |
Get-ChildItem -Path '$(ob_outputDirectory)\pkgs' -Recurse
displayName: 'List Unsigned Package'
- pwsh: |
$signedFilesPath = '$(ob_outputDirectory)\Signed-$(Runtime)'
Remove-Item -Path $signedFilesPath -Recurse -Force -Verbose
displayName: 'Remove Signed-$(Runtime) folder'
- stage: Pack_MSIXBundle_And_Sign
displayName: 'Pack and sign MSIXBundle'
dependsOn: [Build_MSIX_Package]
variables:
EnabledChannels: $[ stageDependencies.Build_MSIX_Package.Build.outputs['x64.BuildMSIXPackage.EnabledChannels'] ]
jobs:
- template: /.pipelines/templates/create-msixbundle-vpack.yml@self
parameters:
Channel: 'LTS'
createVPack: ${{ parameters.createVPack }}
- template: /.pipelines/templates/create-msixbundle-vpack.yml@self
parameters:
Channel: 'Stable'
createVPack: ${{ parameters.createVPack }}
- stage: Publish_Symbols
displayName: 'Publish Symbols'
dependsOn: [Pack_MSIXBundle_And_Sign]
jobs:
- job: PublishSymbols
pool:
type: windows
variables:
ob_outputDirectory: '$(BUILD.SOURCESDIRECTORY)\out'
steps:
- checkout: self
displayName: Checkout source code - during restore
clean: true
path: s ## $(Build.SourcesDirectory) is at '$(Pipeline.Workspace)\s', so we need to check out repo to the 's' folder.
env:
ob_restore_phase: true
- pwsh: |
Get-ChildItem Env: | Out-String -Width 9999
displayName: 'Capture Environment Variables'
- task: DownloadPipelineArtifact@2
inputs:
artifactName: drop_build_x64
itemPattern: |
**/symbols-*.zip
targetPath: '$(Build.ArtifactStagingDirectory)\downloads'
displayName: Download symbols for x64
- task: DownloadPipelineArtifact@2
inputs:
artifactName: drop_build_arm64
itemPattern: |
**/symbols-*.zip
targetPath: '$(Build.ArtifactStagingDirectory)\downloads'
displayName: Download symbols for arm64
- pwsh: |
$downloadDir = '$(Build.ArtifactStagingDirectory)\downloads'
Write-Verbose -Verbose "Enumerating $downloadDir"
$downloadedArtifacts = Get-ChildItem -Path $downloadDir -Recurse -Filter 'symbols-*.zip'
$downloadedArtifacts | Out-String -Width 9999
$expandedRoot = New-Item -Path "$(Pipeline.Workspace)\expanded" -ItemType Directory -Verbose
$downloadedArtifacts | ForEach-Object {
$expandDir = Join-Path $expandedRoot $_.BaseName
Write-Verbose -Verbose "Expanding $($_.FullName) to $expandDir"
$null = New-Item -Path $expandDir -ItemType Directory -Verbose
Expand-Archive -Path $_.FullName -DestinationPath $expandDir -Force
}
Write-Verbose -Verbose "Enumerating $expandedRoot"
Get-ChildItem -Path $expandedRoot -Recurse | Out-String -Width 9999
$vstsCommandString = "vso[task.setvariable variable=SymbolsPath]$expandedRoot"
Write-Verbose -Message "$vstsCommandString" -Verbose
Write-Host -Object "##$vstsCommandString"
displayName: Expand and capture symbols folders
- task: PublishSymbols@2
condition: and(succeeded(), ${{ parameters.createVPack }})
inputs:
symbolsFolder: '$(SymbolsPath)'
searchPattern: '**/*.pdb'
indexSources: false
publishSymbols: true
symbolServerType: TeamServices
detailedLog: true
@@ -0,0 +1,124 @@
trigger: none
parameters:
- name: InternalSDKBlobURL
displayName: URL to the blob having internal .NET SDK
type: string
default: ' '
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: ReleaseTagVar
displayName: Release Tag
type: string
default: 'fromBranch'
- name: SKIP_SIGNING
displayName: Debugging - Skip Signing
type: string
default: 'NO'
- name: RUN_TEST_AND_RELEASE
displayName: Debugging - Run Test and Release Artifacts Stage
type: boolean
default: true
- name: RUN_WINDOWS
displayName: Debugging - Enable Windows Stage
type: boolean
default: true
- name: ENABLE_MSBUILD_BINLOGS
displayName: Debugging - Enable MSBuild Binary Logs
type: boolean
default: false
- name: FORCE_CODEQL
displayName: Debugging - Enable CodeQL and set cadence to 1 hour
type: boolean
default: false
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: bins-$(BUILD.SOURCEBRANCHNAME)-nonofficial-$(Build.BuildId)
resources:
repositories:
- repository: ComplianceRepo
type: github
endpoint: ComplianceGHRepo
name: PowerShell/compliance
ref: master
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
variables:
- template: /.pipelines/templates/variables/PowerShell-Coordinated_Packages-Variables.yml@self
parameters:
InternalSDKBlobURL: ${{ parameters.InternalSDKBlobURL }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
SKIP_SIGNING: ${{ parameters.SKIP_SIGNING }}
ENABLE_MSBUILD_BINLOGS: ${{ parameters.ENABLE_MSBUILD_BINLOGS }}
FORCE_CODEQL: ${{ parameters.FORCE_CODEQL }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
parameters:
customTags: 'ES365AIMigrationTooling'
featureFlags:
LinuxHostVersion:
Network: KS3
WindowsHostVersion:
Version: 2022
Network: KS3
incrementalSDLBinaryAnalysis: true
globalSdl:
disableLegacyManifest: true
# disabled Armorty as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
enabled: false
sbom:
enabled: true
codeql:
compiled:
enabled: $(CODEQL_ENABLED)
tsaEnabled: true # This enables TSA bug filing only for CodeQL 3000
credscan:
enabled: true
scanFolder: $(Build.SourcesDirectory)
suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json
cg:
enabled: true
ignoreDirectories: '.devcontainer,demos,docker,docs,src,test,tools/packaging'
binskim:
enabled: false
exactToolVersion: 4.4.2
# APIScan requires a non-Ready-To-Run build
apiscan:
enabled: false
tsaOptionsFile: .config\tsaoptions.json
stages:
- template: /.pipelines/templates/stages/PowerShell-Coordinated_Packages-Stages.yml@self
parameters:
RUN_WINDOWS: ${{ parameters.RUN_WINDOWS }}
RUN_TEST_AND_RELEASE: ${{ parameters.RUN_TEST_AND_RELEASE }}
OfficialBuild: false
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
@@ -0,0 +1,123 @@
trigger: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: ForceAzureBlobDelete
displayName: Delete Azure Blob
type: string
values:
- true
- false
default: false
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: InternalSDKBlobURL
displayName: URL to the blob having internal .NET SDK
type: string
default: ' '
- name: ReleaseTagVar
displayName: Release Tag
type: string
default: 'fromBranch'
- name: SKIP_SIGNING
displayName: Skip Signing
type: string
default: 'NO'
- name: disableNetworkIsolation
type: boolean
default: false
- name: IsEarlyAccess
type: boolean
default: false
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: pkgs-$(BUILD.SOURCEBRANCHNAME)-nonofficial-$(Build.BuildId)
variables:
- template: /.pipelines/templates/variables/PowerShell-Packages-Variables.yml@self
parameters:
debug: ${{ parameters.debug }}
ForceAzureBlobDelete: ${{ parameters.ForceAzureBlobDelete }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
disableNetworkIsolation: ${{ parameters.disableNetworkIsolation }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
resources:
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
trigger:
branches:
include:
- master
- releases/*
repositories:
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
parameters:
cloudvault:
enabled: false
featureFlags:
WindowsHostVersion:
Version: 2022
Network: KS3
LinuxHostVersion:
Network: KS3
linuxEsrpSigning: true
incrementalSDLBinaryAnalysis: true
disableNetworkIsolation: ${{ variables.disableNetworkIsolation }}
globalSdl:
disableLegacyManifest: true
# disabled Armorty as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
enabled: false
sbom:
enabled: true
compiled:
enabled: false
credscan:
enabled: true
scanFolder: $(Build.SourcesDirectory)
suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json
cg:
enabled: true
ignoreDirectories: '.devcontainer,demos,docker,docs,src,test,tools/packaging'
binskim:
enabled: false
exactToolVersion: 4.4.2
# APIScan requires a non-Ready-To-Run build
apiscan:
enabled: false
tsaOptionsFile: .config\tsaoptions.json
stages:
- template: /.pipelines/templates/stages/PowerShell-Packages-Stages.yml@self
parameters:
OfficialBuild: false
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
@@ -0,0 +1,82 @@
trigger: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: skipPublish
displayName: Skip PMC Publish
type: boolean
default: false
- name: SKIP_SIGNING
displayName: Skip Signing
type: string
default: 'NO'
name: ev2-$(BUILD.SOURCEBRANCHNAME)-nonofficial-$(Build.BuildId)
variables:
- template: /.pipelines/templates/variables/PowerShell-Release-Azure-Variables.yml@self
parameters:
debug: ${{ parameters.debug }}
resources:
repositories:
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
- pipeline: PSPackagesOfficial
source: 'PowerShell-Packages-NonOfficial'
trigger:
branches:
include:
- master
- releases/*
extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
parameters:
featureFlags:
WindowsHostVersion:
Version: 2022
Network: Netlock
linuxEsrpSigning: true
incrementalSDLBinaryAnalysis: true
cloudvault:
enabled: false
globalSdl:
disableLegacyManifest: true
# disabled Armory as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
enabled: false
tsa:
enabled: true
credscan:
enabled: true
scanFolder: $(Build.SourcesDirectory)
suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json
binskim:
break: false # always break the build on binskim issues in addition to TSA upload
exactToolVersion: 4.4.2
policheck:
break: true # always break the build on policheck issues. You can disable it by setting to 'false'
tsaOptionsFile: $(Build.SourcesDirectory)\.config\tsaoptions.json
stages:
- template: /.pipelines/templates/release-prep-for-ev2.yml@self
parameters:
skipPublish: ${{ parameters.skipPublish }}
# NonOfficial: run the publish stage to verify templateContext artifact download,
# but skip the actual Ev2 push to PMC.
- template: /.pipelines/templates/release-publish-pmc.yml@self
parameters:
releaseEnvironment: Test
stagePrefix: Test
skipEv2Push: true
@@ -0,0 +1,129 @@
trigger: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: InternalSDKBlobURL
displayName: URL to the blob having internal .NET SDK
type: string
default: ' '
- name: ReleaseTagVar
displayName: Release Tag
type: string
default: 'fromBranch'
- name: SKIP_SIGNING
displayName: Skip Signing
type: string
default: 'NO'
- name: SkipPublish
displayName: Skip Publishing to Nuget
type: boolean
default: false
- name: SkipPSInfraInstallers
displayName: Skip Copying Archives and Installers to PSInfrastructure Public Location
type: boolean
default: false
- name: skipMSIXPublish
displayName: Skip MSIX Publish
type: boolean
default: false
- name: EarlyAccessFeed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: release-$(BUILD.SOURCEBRANCHNAME)-nonofficial-$(Build.BuildId)
variables:
- template: /.pipelines/templates/variables/PowerShell-Release-Variables.yml@self
parameters:
debug: ${{ parameters.debug }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
resources:
repositories:
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
- repository: PSInternalTools
type: git
name: PowerShellCore/Internal-PowerShellTeam-Tools
ref: refs/heads/master
pipelines:
- pipeline: CoOrdinatedBuildPipeline
source: 'PowerShell-Coordinated_Packages-NonOfficial'
# NOTE: The alias name "PSPackagesOfficial" is intentionally reused here even
# for the NonOfficial pipeline source. Downstream shared templates (for example,
# release-validate-sdk.yml and release-upload-buildinfo.yml) reference artifacts
# using `download: PSPackagesOfficial`, so changing this alias would break them.
- pipeline: PSPackagesOfficial
source: 'PowerShell-Packages-NonOfficial'
trigger:
branches:
include:
- master
- releases/*
extends:
template: v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates
parameters:
release:
category: NonAzure
featureFlags:
WindowsHostVersion:
Version: 2022
Network: KS3
incrementalSDLBinaryAnalysis: true
cloudvault:
enabled: false
globalSdl:
disableLegacyManifest: true
# disabled Armory as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
enabled: false
tsa:
enabled: true
credscan:
enabled: true
scanFolder: $(Build.SourcesDirectory)
suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json
binskim:
break: false # always break the build on binskim issues in addition to TSA upload
exactToolVersion: 4.4.2
policheck:
break: true # always break the build on policheck issues. You can disable it by setting to 'false'
# suppression:
# suppressionFile: $(Build.SourcesDirectory)\.gdn\global.gdnsuppress
tsaOptionsFile: .config\tsaoptions.json
stages:
- template: /.pipelines/templates/stages/PowerShell-Release-Stages.yml@self
parameters:
releaseEnvironment: Test
SkipPublish: ${{ parameters.SkipPublish }}
SkipPSInfraInstallers: ${{ parameters.SkipPSInfraInstallers }}
skipMSIXPublish: ${{ parameters.skipMSIXPublish }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
@@ -0,0 +1,88 @@
trigger: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: 'createVPack'
displayName: 'Create and Submit VPack'
type: boolean
default: true
- name: vPackName
type: string
displayName: 'VPack Name:'
default: 'PowerShell.BuildTool'
values:
- PowerShell.BuildTool
- PowerShell
- PowerShellDoNotUse
- name: 'ReleaseTagVar'
type: string
displayName: 'Release Tag Var:'
default: 'fromBranch'
- name: 'debug'
displayName: 'Enable debug output'
type: boolean
default: false
- name: netiso
displayName: "Network Isolation Policy"
type: string
values:
- KS4
- R1
- Netlock
default: "R1"
name: vPack_$(Build.SourceBranchName)_NonOfficial_Create.${{ parameters.createVPack }}_Name.${{ parameters.vPackName}}_$(date:yyyyMMdd).$(rev:rr)
variables:
- template: /.pipelines/templates/variables/PowerShell-vPack-Variables.yml@self
parameters:
debug: ${{ parameters.debug }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
netiso: ${{ parameters.netiso }}
resources:
repositories:
- repository: onebranchTemplates
type: git
name: OneBranch.Pipelines/GovernedTemplates
ref: refs/heads/main
extends:
template: v2/Microsoft.NonOfficial.yml@onebranchTemplates
parameters:
platform:
name: 'windows_undocked' # windows undocked
featureFlags:
WindowsHostVersion:
Version: 2022
Network: ${{ variables.netiso }}
cloudvault:
enabled: false
globalSdl:
useCustomPolicy: true # for signing code
disableLegacyManifest: true
# disabled Armory as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
enabled: false
sbom:
enabled: true
compiled:
enabled: false
credscan:
enabled: true
scanFolder: $(Build.SourcesDirectory)
suppressionsFile: $(Build.SourcesDirectory)\.config\suppress.json
binskim:
enabled: false
exactToolVersion: 4.4.2
# APIScan requires a non-Ready-To-Run build
apiscan:
enabled: false
tsaOptionsFile: .config/tsaoptions.json
stages:
- template: /.pipelines/templates/stages/PowerShell-vPack-Stages.yml@self
parameters:
createVPack: ${{ parameters.createVPack }}
vPackName: ${{ parameters.vPackName }}
@@ -29,11 +29,28 @@ parameters:
displayName: Debugging - Enable CodeQL and set cadence to 1 hour
type: boolean
default: false
- name: OfficialBuild
- name: IsEarlyAccess
type: boolean
default: false
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: bins-$(BUILD.SOURCEBRANCHNAME)-prod.${{ parameters.OfficialBuild }}-$(Build.BuildId)
name: bins-$(BUILD.SOURCEBRANCHNAME)-prod-$(Build.BuildId)
resources:
repositories:
@@ -48,68 +65,25 @@ resources:
ref: refs/heads/main
variables:
- name: PS_RELEASE_BUILD
value: 1
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: 1
- name: POWERSHELL_TELEMETRY_OPTOUT
value: 1
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: branchCounterKey
value: $[format('{0:yyyyMMdd}-{1}', pipeline.startTime,variables['Build.SourceBranch'])]
- name: branchCounter
value: $[counter(variables['branchCounterKey'], 1)]
- name: BUILDSECMON_OPT_IN
value: true
- name: __DOTNET_RUNTIME_FEED
value: ${{ parameters.InternalSDKBlobURL }}
- name: LinuxContainerImage
value: mcr.microsoft.com/onebranch/azurelinux/build:3.0
- name: WindowsContainerImage
value: onebranch.azurecr.io/windows/ltsc2019/vse2022:latest
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)]
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
- name: SKIP_SIGNING
value: ${{ parameters.SKIP_SIGNING }}
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- name: ENABLE_MSBUILD_BINLOGS
value: ${{ parameters.ENABLE_MSBUILD_BINLOGS }}
- ${{ if eq(parameters['FORCE_CODEQL'],'true') }}:
# Cadence is hours before CodeQL will allow a re-upload of the database
- name: CodeQL.Cadence
value: 1
- name: CODEQL_ENABLED
${{ if or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(parameters['FORCE_CODEQL'],'true')) }}:
value: true
${{ else }}:
value: false
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates' ) }}
# Fix for BinSkim ICU package error in Linux containers
- name: DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
value: true
# Disable BinSkim at job level to override NonOfficial template defaults
- name: ob_sdl_binskim_enabled
value: false
- name: ps_official_build
value: ${{ parameters.OfficialBuild }}
- template: templates/variables/PowerShell-Coordinated_Packages-Variables.yml
parameters:
InternalSDKBlobURL: ${{ parameters.InternalSDKBlobURL }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
SKIP_SIGNING: ${{ parameters.SKIP_SIGNING }}
ENABLE_MSBUILD_BINLOGS: ${{ parameters.ENABLE_MSBUILD_BINLOGS }}
FORCE_CODEQL: ${{ parameters.FORCE_CODEQL }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
extends:
template: ${{ variables.templateFile }}
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates
parameters:
customTags: 'ES365AIMigrationTooling'
featureFlags:
LinuxHostVersion:
Network: KS3
WindowsHostVersion:
Version: 2022
Network: KS3
incrementalSDLBinaryAnalysis: true
globalSdl:
@@ -139,185 +113,12 @@ extends:
tsaOptionsFile: .config\tsaoptions.json
stages:
- stage: prep
jobs:
- job: SetVars
displayName: Set Variables
pool:
type: linux
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT/BuildJson'
- name: ob_sdl_codeSignValidation_enabled
value: false
- name: ob_sdl_codeql_compiled_enabled
value: false
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_signing_setup_enabled
value: false
- name: ob_sdl_sbom_enabled
value: false
steps:
- checkout: self
clean: true
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase
- pwsh: |
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: Capture environment variables
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: yes
- stage: macos
displayName: macOS - build and sign
dependsOn: ['prep']
jobs:
- template: /.pipelines/templates/mac.yml@self
parameters:
buildArchitecture: x64
- template: /.pipelines/templates/mac.yml@self
parameters:
buildArchitecture: arm64
- stage: linux
displayName: linux - build and sign
dependsOn: ['prep']
jobs:
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-x64'
JobName: 'linux_x64'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-x64'
JobName: 'linux_x64_minSize'
BuildConfiguration: 'minSize'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-arm'
JobName: 'linux_arm'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-arm64'
JobName: 'linux_arm64'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-linux-x64'
JobName: 'linux_fxd_x64_mariner'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-linux-arm64'
JobName: 'linux_fxd_arm64_mariner'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-noopt-linux-musl-x64'
JobName: 'linux_fxd_x64_alpine'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent'
JobName: 'linux_fxd'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-musl-x64'
JobName: 'linux_x64_alpine'
- stage: windows
displayName: windows - build and sign
dependsOn: ['prep']
condition: and(succeeded(),eq('${{ parameters.RUN_WINDOWS }}','true'))
jobs:
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x64
BuildConfiguration: release
JobName: build_windows_x64_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x64
BuildConfiguration: minSize
JobName: build_windows_x64_minSize_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x86
JobName: build_windows_x86_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: arm64
JobName: build_windows_arm64_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: fxdependent
JobName: build_windows_fxdependent_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: fxdependentWinDesktop
JobName: build_windows_fxdependentWinDesktop_release
- stage: test_and_release_artifacts
displayName: Test and Release Artifacts
dependsOn: ['prep']
condition: and(succeeded(),eq('${{ parameters.RUN_TEST_AND_RELEASE }}','true'))
jobs:
- template: /.pipelines/templates/testartifacts.yml@self
- job: release_json
displayName: Create and Upload release.json
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
steps:
- checkout: self
clean: true
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
- template: /.pipelines/templates/rebuild-branch-check.yml@self
- powershell: |
$metadata = Get-Content '$(Build.SourcesDirectory)/PowerShell/tools/metadata.json' -Raw | ConvertFrom-Json
# Use the rebuild branch check from the template
$isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true'
# Don't mark as LTS release for rebuild branches
$LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch
if ($isRebuildBranch) {
Write-Verbose -Message "Rebuild branch detected, not marking as LTS release" -Verbose
}
@{ ReleaseVersion = "$(Version)"; LTSRelease = $LTS } | ConvertTo-Json | Out-File "$(Build.StagingDirectory)\release.json"
Get-Content "$(Build.StagingDirectory)\release.json"
if (-not (Test-Path "$(ob_outputDirectory)\metadata")) {
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\metadata"
}
Copy-Item -Path "$(Build.StagingDirectory)\release.json" -Destination "$(ob_outputDirectory)\metadata" -Force
displayName: Create and upload release.json file to build artifact
retryCountOnTaskFailure: 2
- template: /.pipelines/templates/step/finalize.yml@self
- template: templates/stages/PowerShell-Coordinated_Packages-Stages.yml
parameters:
RUN_WINDOWS: ${{ parameters.RUN_WINDOWS }}
RUN_TEST_AND_RELEASE: ${{ parameters.RUN_TEST_AND_RELEASE }}
OfficialBuild: true
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
+37 -223
View File
@@ -24,53 +24,41 @@ parameters: # parameters are shown up in ADO UI in a build queue time
displayName: Skip Signing
type: string
default: 'NO'
- name: OfficialBuild
type: boolean
default: false
- name: disableNetworkIsolation
type: boolean
default: false
- name: IsEarlyAccess
type: boolean
default: false
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: pkgs-$(BUILD.SOURCEBRANCHNAME)-prod.${{ parameters.OfficialBuild }}-$(Build.BuildId)
name: pkgs-$(BUILD.SOURCEBRANCHNAME)-prod-$(Build.BuildId)
variables:
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)] # needed for onebranch.pipeline.version task
- name: system.debug
value: ${{ parameters.debug }}
- name: ENABLE_PRS_DELAYSIGN
value: 1
- name: ROOT
value: $(Build.SourcesDirectory)
- name: ForceAzureBlobDelete
value: ${{ parameters.ForceAzureBlobDelete }}
- name: NUGET_XMLDOC_MODE
value: none
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: WindowsContainerImage
value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' # Docker image which is used to build the project
- name: LinuxContainerImage
value: mcr.microsoft.com/onebranch/azurelinux/build:3.0
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- name: branchCounterKey
value: $[format('{0:yyyyMMdd}-{1}', pipeline.startTime,variables['Build.SourceBranch'])]
- name: branchCounter
value: $[counter(variables['branchCounterKey'], 1)]
- group: MSIXSigningProfile
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates' ) }}
- name: disableNetworkIsolation
value: ${{ parameters.disableNetworkIsolation }}
- template: templates/variables/PowerShell-Packages-Variables.yml
parameters:
debug: ${{ parameters.debug }}
ForceAzureBlobDelete: ${{ parameters.ForceAzureBlobDelete }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
disableNetworkIsolation: ${{ parameters.disableNetworkIsolation }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
resources:
pipelines:
@@ -89,7 +77,7 @@ resources:
ref: refs/heads/main
extends:
template: ${{ variables.templateFile }}
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates
parameters:
cloudvault:
enabled: false
@@ -126,184 +114,10 @@ extends:
enabled: false
tsaOptionsFile: .config\tsaoptions.json
stages:
- stage: prep
displayName: 'Prep BuildInfo+Az'
jobs:
- template: /.pipelines/templates/checkAzureContainer.yml@self
- stage: mac_package
displayName: 'macOS Pkg+Sign'
dependsOn: []
jobs:
- template: /.pipelines/templates/mac-package-build.yml@self
parameters:
buildArchitecture: x64
- template: /.pipelines/templates/mac-package-build.yml@self
parameters:
buildArchitecture: arm64
- stage: windows_package_build
displayName: 'Win Pkg (unsigned)'
dependsOn: []
jobs:
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: x64
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: arm64
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: x86
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: fxdependent
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: fxdependentWinDesktop
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: minsize
- stage: windows_package_sign
displayName: 'Win Pkg Sign'
dependsOn: [windows_package_build]
jobs:
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: x64
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: arm64
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: x86
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: fxdependent
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: fxdependentWinDesktop
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: minsize
- stage: linux_package
displayName: 'Linux Pkg+Sign'
dependsOn: []
jobs:
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: deb
jobName: deb
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_x64_mariner'
signedDrop: 'drop_linux_sign_linux_fxd_x64_mariner'
packageType: rpm-fxdependent #mariner-x64
jobName: mariner_x64
signingProfile: 'CP-459159-pgpdetached'
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_arm64_mariner'
signedDrop: 'drop_linux_sign_linux_fxd_arm64_mariner'
packageType: rpm-fxdependent-arm64 #mariner-arm64
jobName: mariner_arm64
signingProfile: 'CP-459159-pgpdetached'
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: rpm
jobName: rpm
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm'
signedDrop: 'drop_linux_sign_linux_arm'
packageType: tar-arm
jobName: tar_arm
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm64'
signedDrop: 'drop_linux_sign_linux_arm64'
packageType: tar-arm64
jobName: tar_arm64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64_alpine'
signedDrop: 'drop_linux_sign_linux_x64_alpine'
packageType: tar-alpine
jobName: tar_alpine
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd'
signedDrop: 'drop_linux_sign_linux_fxd'
packageType: fxdependent
jobName: fxdependent
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: tar
jobName: tar
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_x64_alpine'
signedDrop: 'drop_linux_sign_linux_fxd_x64_alpine'
packageType: tar-alpine-fxdependent
jobName: tar_alpine_fxd
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64_minSize'
signedDrop: 'drop_linux_sign_linux_x64_minSize'
packageType: min-size
jobName: minSize
- stage: nupkg
displayName: 'NuGet Pkg+Sign'
dependsOn: []
jobs:
- template: /.pipelines/templates/nupkg.yml@self
- stage: msixbundle
displayName: 'MSIX Bundle+Sign'
dependsOn: [windows_package_build] # Only depends on unsigned packages
jobs:
- template: /.pipelines/templates/package-create-msix.yml@self
parameters:
OfficialBuild: ${{ parameters.OfficialBuild }}
- stage: upload
displayName: 'Upload'
dependsOn: [prep, mac_package, windows_package_sign, linux_package, nupkg, msixbundle] # prep needed for BuildInfo JSON
jobs:
- template: /.pipelines/templates/uploadToAzure.yml@self
- stage: validatePackages
displayName: 'Validate Packages'
dependsOn: [upload]
jobs:
- template: /.pipelines/templates/release-validate-packagenames.yml@self
- template: templates/stages/PowerShell-Packages-Stages.yml
parameters:
OfficialBuild: true
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
@@ -13,44 +13,13 @@ parameters: # parameters are shown up in ADO UI in a build queue time
displayName: Skip Signing
type: string
default: 'NO'
- name: OfficialBuild
type: boolean
default: false
name: ev2-$(BUILD.SOURCEBRANCHNAME)-prod.${{ parameters.OfficialBuild }}-$(Build.BuildId)
name: ev2-$(BUILD.SOURCEBRANCHNAME)-prod-$(Build.BuildId)
variables:
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)]
- name: system.debug
value: ${{ parameters.debug }}
- name: ENABLE_PRS_DELAYSIGN
value: 1
- name: ROOT
value: $(Build.SourcesDirectory)
- name: REPOROOT
value: $(Build.SourcesDirectory)
- name: OUTPUTROOT
value: $(REPOROOT)\out
- name: NUGET_XMLDOC_MODE
value: none
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\.config\tsaoptions.json
- name: WindowsContainerImage
value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest'
- name: LinuxContainerImage
value: mcr.microsoft.com/onebranch/azurelinux/build:3.0
- group: PoolNames
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates' ) }}
- template: templates/variables/PowerShell-Release-Azure-Variables.yml
parameters:
debug: ${{ parameters.debug }}
resources:
repositories:
@@ -72,7 +41,7 @@ resources:
- releases/*
extends:
template: ${{ variables.templateFile }}
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates
parameters:
featureFlags:
WindowsHostVersion:
@@ -98,7 +67,7 @@ extends:
exactToolVersion: 4.4.2
policheck:
break: true # always break the build on policheck issues. You can disable it by setting to 'false'
tsaOptionsFile: .config\tsaoptions.json
tsaOptionsFile: $(Build.SourcesDirectory)\.config\tsaoptions.json
stages:
- template: /.pipelines/templates/release-prep-for-ev2.yml@self
parameters:
+33 -351
View File
@@ -29,49 +29,33 @@ parameters: # parameters are shown up in ADO UI in a build queue time
displayName: Skip MSIX Publish
type: boolean
default: false
- name: OfficialBuild
- name: EarlyAccessFeed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: release-$(BUILD.SOURCEBRANCHNAME)-prod.${{ parameters.OfficialBuild }}-$(Build.BuildId)
name: release-$(BUILD.SOURCEBRANCHNAME)-prod-$(Build.BuildId)
variables:
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)]
- name: system.debug
value: ${{ parameters.debug }}
- name: ENABLE_PRS_DELAYSIGN
value: 1
- name: ROOT
value: $(Build.SourcesDirectory)
- name: REPOROOT
value: $(Build.SourcesDirectory)
- name: OUTPUTROOT
value: $(REPOROOT)\out
- name: NUGET_XMLDOC_MODE
value: none
- name: nugetMultiFeedWarnLevel
value: none
- name: NugetSecurityAnalysisWarningLevel
value: none
- name: skipNugetSecurityAnalysis
value: true
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: WindowsContainerImage
value: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest'
- name: LinuxContainerImage
value: mcr.microsoft.com/onebranch/azurelinux/build:3.0
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
- group: PoolNames
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates', 'v2/OneBranch.NonOfficial.CrossPlat.yml@onebranchTemplates' ) }}
- name: releaseEnvironment
value: ${{ iif ( parameters.OfficialBuild, 'Production', 'Test' ) }}
# Fix for BinSkim ICU package error in Linux containers
- name: DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
value: true
- template: templates/variables/PowerShell-Release-Variables.yml
parameters:
debug: ${{ parameters.debug }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
resources:
repositories:
@@ -97,7 +81,7 @@ resources:
- releases/*
extends:
template: ${{ variables.templateFile }}
template: v2/OneBranch.Official.CrossPlat.yml@onebranchTemplates
parameters:
release:
category: NonAzure
@@ -129,315 +113,13 @@ extends:
tsaOptionsFile: .config\tsaoptions.json
stages:
- stage: setReleaseTagAndChangelog
displayName: 'Set Release Tag and Upload Changelog'
jobs:
- template: /.pipelines/templates/release-SetTagAndChangelog.yml@self
- stage: validateSdk
displayName: 'Validate SDK'
dependsOn: []
jobs:
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "windowsSDK"
displayName: "Windows SDK Validation"
imageName: PSMMS2019-Secure
poolName: $(windowsPool)
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "MacOSSDK"
displayName: "MacOS SDK Validation"
imageName: macOS-latest
poolName: Azure Pipelines
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "LinuxSDK"
displayName: "Linux SDK Validation"
imageName: PSMMSUbuntu22.04-Secure
poolName: $(ubuntuPool)
- stage: gbltool
displayName: 'Validate Global tools'
dependsOn: []
jobs:
- template: /.pipelines/templates/release-validate-globaltools.yml@self
parameters:
jobName: "WindowsGlobalTools"
displayName: "Windows Global Tools Validation"
jobtype: windows
- template: /.pipelines/templates/release-validate-globaltools.yml@self
parameters:
jobName: "LinuxGlobalTools"
displayName: "Linux Global Tools Validation"
jobtype: linux
globalToolExeName: 'pwsh'
globalToolPackageName: 'PowerShell.Linux.x64'
- stage: fxdpackages
displayName: 'Validate FXD Packages'
dependsOn: []
jobs:
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'winfxd'
displayName: 'Validate Win Fxd Packages'
jobtype: 'windows'
artifactName: 'drop_windows_package_package_win_fxdependent'
packageNamePattern: '**/*win-fxdependent.zip'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'winfxdDesktop'
displayName: 'Validate WinDesktop Fxd Packages'
jobtype: 'windows'
artifactName: 'drop_windows_package_package_win_fxdependentWinDesktop'
packageNamePattern: '**/*win-fxdependentwinDesktop.zip'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'linuxfxd'
displayName: 'Validate Linux Fxd Packages'
jobtype: 'linux'
artifactName: 'drop_linux_package_fxdependent'
packageNamePattern: '**/*linux-x64-fxdependent.tar.gz'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'linuxArm64fxd'
displayName: 'Validate Linux ARM64 Fxd Packages'
jobtype: 'linux'
artifactName: 'drop_linux_package_fxdependent'
# this is really an architecture independent package
packageNamePattern: '**/*linux-x64-fxdependent.tar.gz'
arm64: 'yes'
enableCredScan: false
- stage: ManualValidation
dependsOn: []
displayName: Manual Validation
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Validate Windows Packages
jobName: ValidateWinPkg
instructions: |
Validate zip package on windows
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Validate OSX Packages
jobName: ValidateOsxPkg
instructions: |
Validate tar.gz package on osx-arm64
- stage: ReleaseAutomation
dependsOn: []
displayName: 'Release Automation'
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Start Release Automation
jobName: StartRA
instructions: |
Kick off Release automation build at: https://dev.azure.com/powershell-rel/Release-Automation/_build?definitionId=10&_a=summary
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Triage results
jobName: TriageRA
dependsOnJob: StartRA
instructions: |
Triage ReleaseAutomation results
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Signoff Tests
dependsOnJob: TriageRA
jobName: SignoffTests
instructions: |
Signoff ReleaseAutomation results
- stage: UpdateChangeLog
displayName: Update the changelog
dependsOn:
- ManualValidation
- ReleaseAutomation
- fxdpackages
- gbltool
- validateSdk
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make sure the changelog is updated
jobName: MergeChangeLog
instructions: |
Update and merge the changelog for the release.
This step is required for creating GitHub draft release.
- stage: PublishGitHubReleaseAndNuget
displayName: Publish GitHub and Nuget Release
dependsOn:
- setReleaseTagAndChangelog
- UpdateChangeLog
variables:
ob_release_environment: ${{ variables.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-githubNuget.yml@self
parameters:
skipPublish: ${{ parameters.SkipPublish }}
- stage: PushGitTagAndMakeDraftPublic
displayName: Push Git Tag and Make Draft Public
dependsOn: PublishGitHubReleaseAndNuget
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Push Git Tag
jobName: PushGitTag
instructions: |
Push the git tag to upstream
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make Draft Public
dependsOnJob: PushGitTag
jobName: DraftPublic
instructions: |
Make the GitHub Release Draft Public
- stage: BlobPublic
displayName: Make Blob Public
dependsOn:
- UpdateChangeLog
- PushGitTagAndMakeDraftPublic
jobs:
- template: /.pipelines/templates/release-MakeBlobPublic.yml@self
parameters:
SkipPSInfraInstallers: ${{ parameters.SkipPSInfraInstallers }}
- stage: PublishPMC
displayName: Publish PMC
dependsOn: PushGitTagAndMakeDraftPublic
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Publish to PMC
jobName: ReleaseToPMC
instructions: |
Run PowerShell-Release-Official-Azure.yml pipeline to publish to PMC
- stage: UpdateDotnetDocker
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Update DotNet SDK Docker images
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Update .NET SDK docker images
jobName: DotnetDocker
instructions: |
Create PR for updating dotnet-docker images to use latest PowerShell version.
1. Fork and clone https://github.com/dotnet/dotnet-docker.git
2. git checkout upstream/nightly -b updatePS
3. dotnet run --project .\eng\update-dependencies\ specific <dotnetversion> --product-version powershell=<powershellversion> --compute-shas
4. create PR targeting nightly branch
- stage: UpdateWinGet
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Add manifest entry to winget
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Add manifest entry to winget
jobName: UpdateWinGet
instructions: |
This is typically done by the community 1-2 days after the release.
- stage: PublishMsix
dependsOn:
- setReleaseTagAndChangelog
- PushGitTagAndMakeDraftPublic
displayName: Publish MSIX to store
variables:
ob_release_environment: ${{ variables.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-MSIX-Publish.yml@self
parameters:
skipMSIXPublish: ${{ parameters.skipMSIXPublish }}
- stage: PublishVPack
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Release vPack
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Start 2 vPack Release pipelines
jobName: PublishVPack
instructions: |
1. Kick off PowerShell-vPack-Official pipeline
2. Kick off PowerShell-MSIXBundle-VPack pipeline
# Need to verify if the Az PS / CLI team still uses this. Skippinng for this release.
# - stage: ReleaseDeps
# dependsOn: GitHubTasks
# displayName: Update pwsh.deps.json links
# jobs:
# - template: templates/release-UpdateDepsJson.yml
- stage: UploadBuildInfoJson
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Upload BuildInfo.json
jobs:
- template: /.pipelines/templates/release-upload-buildinfo.yml@self
- stage: ReleaseSymbols
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Release Symbols
jobs:
- template: /.pipelines/templates/release-symbols.yml@self
- stage: ChangesToMaster
displayName: Ensure changes are in GH master
dependsOn:
- PublishPMC
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make sure changes are in master
jobName: MergeToMaster
instructions: |
Make sure that changes README.md and metadata.json are merged into master on GitHub.
- stage: ReleaseToMU
displayName: Release to MU
dependsOn: PushGitTagAndMakeDraftPublic # This only needs the blob to be available
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Release to MU
instructions: |
Notify the PM team to start the process of releasing to MU.
- stage: ReleaseClose
displayName: Finish Release
dependsOn:
- ReleaseToMU
- ReleaseSymbols
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Retain Build
jobName: RetainBuild
instructions: |
Retain the build
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Delete release branch
jobName: DeleteBranch
instructions: |
Delete release
- template: templates/stages/PowerShell-Release-Stages.yml
parameters:
releaseEnvironment: Production
SkipPublish: ${{ parameters.SkipPublish }}
SkipPSInfraInstallers: ${{ parameters.SkipPSInfraInstallers }}
skipMSIXPublish: ${{ parameters.skipMSIXPublish }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
+39 -265
View File
@@ -1,9 +1,6 @@
trigger: none
parameters: # parameters are shown up in ADO UI in a build queue time
- name: OfficialBuild
type: boolean
default: true
- name: 'createVPack'
displayName: 'Create and Submit VPack'
type: boolean
@@ -32,40 +29,39 @@ parameters: # parameters are shown up in ADO UI in a build queue time
- R1
- Netlock
default: "R1"
- name: IsEarlyAccess
type: boolean
default: false
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net11'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
name: vPack_$(Build.SourceBranchName)_Prod.${{ parameters.OfficialBuild }}_Create.${{ parameters.createVPack }}_Name.${{ parameters.vPackName}}_$(date:yyyyMMdd).$(rev:rr)
name: vPack_$(Build.SourceBranchName)_Prod_Create.${{ parameters.createVPack }}_Name.${{ parameters.vPackName}}_$(date:yyyyMMdd).$(rev:rr)
variables:
- name: CDP_DEFINITION_BUILD_COUNT
value: $[counter('', 0)]
- name: system.debug
value: ${{ parameters.debug }}
- name: BuildSolution
value: $(Build.SourcesDirectory)\dirs.proj
- name: BuildConfiguration
value: Release
- name: WindowsContainerImage
value: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest'
- name: Codeql.Enabled
value: false # pipeline is not building artifacts; it repackages existing artifacts into a vpack
- name: DOTNET_CLI_TELEMETRY_OPTOUT
value: 1
- name: POWERSHELL_TELEMETRY_OPTOUT
value: 1
- name: nugetMultiFeedWarnLevel
value: none
- name: ReleaseTagVar
value: ${{ parameters.ReleaseTagVar }}
- group: Azure Blob variable group
- group: certificate_logical_to_actual # used within signing task
- name: templateFile
value: ${{ iif ( parameters.OfficialBuild, 'v2/Microsoft.Official.yml@onebranchTemplates', 'v2/Microsoft.NonOfficial.yml@onebranchTemplates' ) }}
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual
- name: netiso
value: ${{ parameters.netiso }}
# We shouldn't be using PATs anymore
# - group: mscodehub-feed-read-general
- template: templates/variables/PowerShell-vPack-Variables.yml
parameters:
debug: ${{ parameters.debug }}
ReleaseTagVar: ${{ parameters.ReleaseTagVar }}
netiso: ${{ parameters.netiso }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
resources:
repositories:
@@ -75,7 +71,7 @@ resources:
ref: refs/heads/main
extends:
template: ${{ variables.templateFile }}
template: v2/Microsoft.Official.yml@onebranchTemplates
parameters:
platform:
name: 'windows_undocked' # windows undocked
@@ -89,7 +85,6 @@ extends:
enabled: false
globalSdl:
useCustomPolicy: true # for signing code
disableLegacyManifest: true
# disabled Armory as we dont have any ARM templates to scan. It fails on some sample ARM templates.
armory:
@@ -110,232 +105,11 @@ extends:
enabled: false
tsaOptionsFile: .config/tsaoptions.json
stages:
- stage: BuildStage
jobs:
- job: BuildJob
pool:
type: windows
strategy:
matrix:
x86:
architecture: x86
x64:
architecture: x64
arm64:
architecture: arm64
variables:
ArtifactPlatform: 'windows'
ob_artifactBaseName: drop_build_$(architecture)
ob_outputDirectory: '$(BUILD.SOURCESDIRECTORY)\out'
ob_createvpack_enabled: ${{ parameters.createVPack }}
ob_createvpack_owneralias: tplunk
ob_createvpack_versionAs: parts
ob_createvpack_propsFile: true
ob_createvpack_verbose: true
ob_createvpack_packagename: '${{ parameters.vPackName }}.$(architecture)'
ob_createvpack_description: PowerShell $(architecture) $(version)
# I think the variables reload after we transition back to the host so this works. 🤷‍♂️
ob_createvpack_majorVer: $(pwshMajorVersion)
ob_createvpack_minorVer: $(pwshMinorVersion)
ob_createvpack_patchVer: $(pwshPatchVersion)
${{ if ne(variables['pwshPrereleaseVersion'], '') }}:
ob_createvpack_prereleaseVer: $(pwshPrereleaseVersion)
${{ else }}:
ob_createvpack_prereleaseVer: $(Build.SourceVersion)
steps:
- checkout: self
displayName: Checkout source code - during restore
clean: true
path: s
env:
ob_restore_phase: true
- template: .pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: yes
- pwsh: |
$version = '$(Version)'
Write-Verbose -Verbose "Version: $version"
if(!$version) {
throw "Version is not set."
}
$mainVersionParts = $version -split '-'
Write-Verbose -Verbose "mainVersionParts: $($mainVersionParts[0]) ; $($mainVersionParts[1])"
$versionParts = $mainVersionParts[0] -split '[.]';
$major = $versionParts[0]
$minor = $versionParts[1]
$patch = $versionParts[2]
$previewPart = $mainVersionParts[1]
Write-Verbose -Verbose "previewPart: $previewPart"
Write-Host "major: $major; minor: $minor; patch: $patch;"
$vstsCommandString = "vso[task.setvariable variable=pwshMajorVersion]$major"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
$vstsCommandString = "vso[task.setvariable variable=pwshMinorVersion]$minor"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
$vstsCommandString = "vso[task.setvariable variable=pwshPatchVersion]$patch"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
if($previewPart) {
$vstsCommandString = "vso[task.setvariable variable=pwshPrereleaseVersion]$previewPart"
} else {
Write-Verbose -Verbose "No prerelease part found in version string."
}
displayName: Set ob_createvpack_*Ver
env:
ob_restore_phase: true
# Validate pwsh*Version variables
- pwsh: |
$variables = @("pwshMajorVersion", "pwshMinorVersion", "pwshPatchVersion")
foreach ($var in $variables) {
if (-not (get-item "Env:\$var" -ErrorAction SilentlyContinue).value) {
throw "Required variable '`$env:$var' is not set."
}
}
displayName: Validate pwsh*Version variables
env:
ob_restore_phase: true
- pwsh: |
if($env:RELEASETAGVAR -match '-') {
throw "Don't release a preview build without coordinating with Windows Engineering Build Tools Team"
}
displayName: Stop any preview release
env:
ob_restore_phase: true
- task: UseDotNet@2
displayName: 'Use .NET Core sdk'
inputs:
packageType: sdk
version: 3.1.x
installationPath: $(Agent.ToolsDirectory)/dotnet
### BUILD ###
- template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self
parameters:
repoRoot: $(repoRoot)
- task: CodeQL3000Init@0 # Add CodeQL Init task right before your 'Build' step.
env:
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
inputs:
Enabled: true
AnalyzeInPipeline: false # Do not upload results
Language: csharp
- task: UseDotNet@2
displayName: 'Install .NET based on global.json'
inputs:
useGlobalJson: true
workingDirectory: $(repoRoot)
env:
ob_restore_phase: true
- pwsh: |
# Need to set PowerShellRoot variable for obp-file-signing template
$vstsCommandString = "vso[task.setvariable variable=PowerShellRoot]$(repoRoot)"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
$Architecture = '$(Architecture)'
$runtime = switch ($Architecture)
{
"x64" { "win7-x64" }
"x86" { "win7-x86" }
"arm64" { "win-arm64" }
}
$params = @{}
if ($env:BuildConfiguration -eq 'minSize') {
$params['ForMinimalSize'] = $true
}
$vstsCommandString = "vso[task.setvariable variable=Runtime]$runtime"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
Write-Verbose -Message "Building PowerShell with Runtime: $runtime for '$env:BuildConfiguration' configuration"
Import-Module -Name $(repoRoot)/build.psm1 -Force
$buildWithSymbolsPath = New-Item -ItemType Directory -Path "$(Pipeline.Workspace)/Symbols_$Architecture" -Force
Start-PSBootstrap -Scenario Package
$null = New-Item -ItemType Directory -Path $buildWithSymbolsPath -Force -Verbose
$ReleaseTagParam = @{}
if ($env:RELEASETAGVAR) {
$ReleaseTagParam['ReleaseTag'] = $env:RELEASETAGVAR
}
Start-PSBuild -Runtime $runtime -Configuration Release -Output $buildWithSymbolsPath -Clean -PSModuleRestore @params @ReleaseTagParam
$refFolderPath = Join-Path $buildWithSymbolsPath 'ref'
Write-Verbose -Verbose "refFolderPath: $refFolderPath"
$outputPath = Join-Path '$(ob_outputDirectory)' 'psoptions'
$null = New-Item -ItemType Directory -Path $outputPath -Force
$psOptPath = "$outputPath/psoptions.json"
Save-PSOptions -PSOptionsPath $psOptPath
Write-Verbose -Verbose "Completed building PowerShell for '$env:BuildConfiguration' configuration"
displayName: Build Windows Universal - $(Architecture) -$(BuildConfiguration) Symbols folder
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
- task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step.
env:
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
inputs:
sourceScanPath: '$(repoRoot)\src'
ob_restore_phase: true
- template: /.pipelines/templates/obp-file-signing.yml@self
parameters:
binPath: '$(Pipeline.Workspace)/Symbols_$(Architecture)'
SigningProfile: $(windows_build_tools_cert_id)
OfficialBuild: false
vPackScenario: true
### END OF BUILD ###
- pwsh: |
Get-ChildItem env:/ob_createvpack_*Ver
Get-ChildItem -Path "$(Pipeline.Workspace)\Symbols_$(Architecture)\*" -Recurse
Get-Content "$(Pipeline.Workspace)\PowerShell\preview.json" -ErrorAction SilentlyContinue | Write-Host
displayName: Debug Output Directory and Version
condition: succeededOrFailed()
- pwsh: |
Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: Capture Environment
condition: succeededOrFailed()
- pwsh: |
$vpackFiles = Get-ChildItem -Path "$(Pipeline.Workspace)\Symbols_$(Architecture)\*" -Recurse
if($vpackFiles.Count -eq 0) {
throw "No files found in $(Pipeline.Workspace)\Symbols_$(Architecture)"
}
$vpackFiles
displayName: Debug Output Directory and Version
condition: succeededOrFailed()
- template: templates/stages/PowerShell-vPack-Stages.yml
parameters:
createVPack: ${{ parameters.createVPack }}
vPackName: ${{ parameters.vPackName }}
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
+50 -5
View File
@@ -4,11 +4,28 @@ name: apiscan-genNotice-$(BUILD.SOURCEBRANCHNAME)-$(Build.BuildId)
trigger: none
parameters:
- name: FORCE_CODEQL
displayName: Debugging - Enable CodeQL and set cadence to 1 hour
- name: IsEarlyAccess
type: boolean
default: false
- name: SkipVerifyPackages
- name: EarlyAccessFeed
displayName: Early Access Feed
type: string
default: 'net10'
values:
- 'net8'
- 'net9'
- 'net10'
- 'net11'
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: FORCE_CODEQL
displayName: Debugging - Enable CodeQL and set cadence to 1 hour
type: boolean
default: false
@@ -25,6 +42,12 @@ variables:
# Defines the variables CgPat, CgOrganization, and CgProject
- group: 'ComponentGovernance'
- group: 'PoolNames'
- name: EARLY_ACCESS_FEED
value: ${{ parameters.EarlyAccessFeed }}
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
- name: DOTNET_SDK_VERSION
value: ${{ parameters.DOTNET_SDK_VERSION }}
- name: LinuxContainerImage
value: mcr.microsoft.com/onebranch/azurelinux/build:3.0
- name: WindowsContainerImage
@@ -98,9 +121,32 @@ extends:
break: false
stages:
- stage: prep
displayName: 'Prepare early access .NET'
dependsOn: []
jobs:
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
parameters:
DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
- ${{ else }}:
- job: skip_download_dotnet_early_access
displayName: 'Skip early access .NET download'
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_signing_setup_enabled
value: false
- name: ob_sdl_codeSignValidation_enabled
value: false
steps:
- pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET download.'
- stage: APIScan
displayName: 'ApiScan'
dependsOn: []
dependsOn: [prep]
jobs:
- template: /.pipelines/templates/compliance/apiscan.yml@self
parameters:
@@ -112,4 +158,3 @@ extends:
- template: /.pipelines/templates/compliance/generateNotice.yml@self
parameters:
parentJobs: []
SkipVerifyPackages: ${{ parameters.SkipVerifyPackages }}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminál</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Příkazový řádek</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automatizace</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automatizace úloh</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Skriptování</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell je prostředí příkazového řádku a skriptovací jazyk založený na platformě .NET se zaměřením na úlohy. PowerShell pomáhá správcům systému a pokročilým uživatelům rychle automatizovat úlohy, které spravují operační systémy (Linux, macOS a Windows) a procesy.
Příkazy PowerShellu umožňují spravovat počítače z příkazového řádku. Zprostředkovatelé PowerShellu umožňují přístup k úložištím dat, jako jsou registr a úložiště certifikátů, stejně snadno jako k systému souborů. PowerShell obsahuje pokročilý analyzátor výrazů a plnohodnotný skriptovací jazyk.
PowerShell je opensourcový. Viz https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Verze: ___VERSION___
Protokol změn: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Interaktivní prostředí</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Skriptovací jazyk</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Vzdálená správa</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Befehlszeile</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automatisierung</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Aufgabenautomatisierung</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Skripterstellung</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell ist eine aufgabenbasierte Befehlszeilenshell und Skriptsprache, die auf .NET basiert. PowerShell unterstützt Systemadministratoren und Power-User bei der schnellen Automatisierung von Aufgaben zur Verwaltung von Betriebssystemen (Linux, macOS und Windows) und Prozessen.
Mit PowerShell-Befehlen können Sie Computer über die Befehlszeile verwalten. Mit PowerShell-Anbietern können Sie genauso einfach auf Datenspeicher wie die Registrierung und den Zertifikatspeicher zugreifen wie auf das Dateisystem. PowerShell enthält einen umfangreichen Ausdrucksparser und eine vollständig entwickelte Skriptsprache.
PowerShell ist Open Source. https://github.com/powershell/powershell anzeigen</Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Version: ___VERSION___
Änderungsprotokoll: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Interaktive Shell</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Skriptsprache</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Remoteverwaltung</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
@@ -1,12 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<AppStoreName _locID="PowerShell-Private">
<!-- This is optional. AppStoreName is typically extracted from your package's AppxManifest DisplayName property. -->
<!-- Uncomment (and localize) this Store name if your application package does not contain a localization for the DisplayName in this language. -->
<!-- Leaving this uncommented for a language that your application package DOES contain a DisplayName for will result in a submission failure with the API. -->
<!-- _locComment_text="{MaxLength=200} App AppStoreName" -->
<!-- Dev Home -->
</AppStoreName>
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
@@ -51,48 +44,9 @@ PowerShell is Open Source. See https://github.com/powershell/powershell </Descr
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=__VERSION_NUMBER__} App Release Note" -->Please see our GitHub releases page for additional details.</ReleaseNotes>
<ScreenshotCaptions>
<!-- Valid length: 200 character limit, up to 9 elements per platform -->
<!-- Valid attributes: any of DesktopImage, MobileImage, XboxImage, SurfaceHubImage, and HoloLensImage -->
<Caption DesktopImage="Prompt.png" _locID="App_caption1">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 1" -->
Prompt
</Caption>
<Caption DesktopImage="Predictor_Inline.png" _locID="App_caption2">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 2" -->
Inline Prediction
</Caption>
<Caption DesktopImage="Predictor_ListView.png" _locID="App_caption3">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 3" -->
Prediction List View
</Caption>
<Caption DesktopImage="Error.png" _locID="App_caption4">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 4" -->
Error Feedback Provider
</Caption>
<Caption DesktopImage="Feedback_Provider.png" _locID="App_caption5">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 5" -->
Feedback Provider
</Caption>
<Caption DesktopImage="Experimental_Features.png" _locID="App_caption6">
<!-- _locComment_text="{MaxLength=200} Screenshot caption 6" -->
Experimental Features
</Caption>
</ScreenshotCaptions>
<AdditionalAssets>
<Icon FileName="pwshLogo.png" />
<!-- Valid elements:-->
<!-- HeroImage414x180, HeroImage846x468, HeroImage558x756, HeroImage414x468, HeroImage558x558, HeroImage2400x1200,-->
<!-- ScreenshotWXGA, ScreenshotHD720, ScreenshotWVGA, Doublewide, Panoramic, Square,-->
<!-- SmallMobileTile, SmallXboxLiveTile, LargeMobileTile, LargeXboxLiveTile, Tile,-->
<!-- DesktopIcon, Icon (use this value for the 1:1 300x300 pixels logo), AchievementIcon,-->
<!-- ChallengePromoIcon, RewardDisplayIcon, Icon150X150, Icon71X71,-->
<!-- BoxArt, BrandedKeyArt, PosterArt, FeaturedPromotionalArt, PromotionalArt16x9, TitledHeroArt-->
<!-- There is no content for any of these elements, just a single attribute called FileName. -->
</AdditionalAssets>
<Trailers>
</Trailers>
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Version: ___VERSION___
Changelog: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Línea de comandos</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automatización</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automatización de tareas</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Scripting</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell es un shell de línea de comandos basado en tareas y un lenguaje de scripting basado en .NET. PowerShell ayuda a los administradores de sistemas y a los usuarios avanzados a automatizar rápidamente las tareas que administran los sistemas operativos (Linux, macOS y Windows) y los procesos.
Los comandos de PowerShell le permiten administrar equipos desde la línea de comandos. Los proveedores de PowerShell le permiten acceder a los almacenes de datos, como el registro y el almacén de certificados, con la misma facilidad con la que accede al sistema de archivos. PowerShell incluye un analizador de expresiones enriquecido y un lenguaje de scripting completamente desarrollado.
PowerShell es de código abierto. Ver https://github.com/powershell/powershell</Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Versión: ___VERSION___
Registro de cambios: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Shell interactivo</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Lenguaje de scripting</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Administración remota</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Ligne de commande</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automation</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automatisation des tâches</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Script</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell est un shell de ligne de commande basé sur des tâches et un langage de script basé sur .NET. PowerShell aide les administrateurs système et les utilisateurs avancés à automatiser rapidement les tâches de gestion des systèmes d’exploitation (Linux, macOS et Windows) et des processus.
Les commandes PowerShell vous permettent de gérer des ordinateurs à partir de la ligne de commande. Les fournisseurs PowerShell vous permettent d’accéder aux magasins de données, tels que le registre et le magasin de certificats, aussi facilement que vous accédez au système de fichiers. PowerShell comprend un analyseur d’expressions enrichi et un langage de script entièrement développé.
PowerShell est open source. Voir https://github.com/powershell/powershell</Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Version : ___VERSION___
Journal des modifications : ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Shell interactif</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Langage de script</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Gestion à distance</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminale</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Riga di comando</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automazione</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automazione delle attività</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Scripting</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell è una shell da riga di comando basata su attività e un linguaggio di scripting basato su .NET. PowerShell consente agli amministratori di sistema e agli utenti esperti di automatizzare rapidamente le attività di gestione dei sistemi operativi (Linux, macOS e Windows) e dei processi.
I comandi di PowerShell consentono di gestire i computer dalla riga di comando. I provider di PowerShell consentono di accedere agli archivi dati, ad esempio l'archivio certificati e del Registro di sistema, con la stessa facilità con cui si accede al file system. PowerShell include un parser di espressioni avanzate e un linguaggio di scripting completamente sviluppato.
PowerShell è open source. Vedi https://github.com/powershell/powershell</Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Versione: ___VERSION___
Log delle modifiche: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Shell interattiva</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Linguaggio di scripting</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Gestione remota</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->シェル</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->ターミナル</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->コマンド ライン</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->自動化</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->タスクの自動化</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->スクリプト</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell は、.NET 上に構築されたタスクベースのコマンドライン シェルおよびスクリプト言語です。 PowerShell は、システム管理者とパワー ユーザーがオペレーティング システム (Linux、macOS、Windows) とプロセスを管理するタスクを迅速に自動化するのに役立ちます。
PowerShell コマンドを使用すると、コマンド ラインからコンピューターを管理できます。 PowerShell プロバイダーを使用すると、レジストリや証明書ストアなどのデータ ストアに、ファイル システムにアクセスするのと同じくらい簡単にアクセスできます。 PowerShell には、豊富な式パーサーと完全に開発されたスクリプト言語が含まれています。
PowerShell はオープン ソースです。 https://github.com/powershell/powershell を表示</Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->バージョン: ___VERSION___
変更ログ: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->対話型シェル</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->スクリプト言語</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->リモート管理</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->셸</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->터미널</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->명령줄</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->자동화</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->작업 자동화</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->스크립팅</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell은 .NET에서 구축된 작업 기반 명령줄 셸 및 스크립팅 언어입니다. PowerShell을 사용하면 시스템 관리자와 전원 사용자가 운영 체제(Linux, macOS 및 Windows) 및 프로세스를 관리하는 작업을 신속하게 자동화할 수 있습니다.
PowerShell 명령을 사용하면 명령줄에서 컴퓨터를 관리할 수 있습니다. PowerShell 공급자는 파일 시스템에 액세스하는 것처럼 쉽게, 레지스트리 및 인증서 저장소와 같은 데이터 저장소에 액세스하도록 지원합니다. PowerShell에는 강력한 식 구문 분석기와 완성도 높은 스크립팅 언어가 포함되어 있습니다.
PowerShell이 오픈 소스로 제공됨. See https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->버전: ___VERSION___
변경 로그: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->대화형 셸</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->스크립트 언어</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->원격 관리</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Powłoka</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Wiersz polecenia</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automatyzacja</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automatyzacja zadań</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Obsługa skryptów</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->Technologia PowerShell to zadaniowa powłoka wiersza polecenia i język skryptowy oparte na platformie .NET. Technologia PowerShell pomaga administratorom systemów i zaawansowanym użytkownikom szybko automatyzować zadania związane z zarządzaniem systemami operacyjnymi (Linux, macOS i Windows) oraz procesami.
Polecenia PowerShell pozwalają zarządzać komputerami z poziomiu wiersza polecenia. Dostawcy PowerShell umożliwiają dostęp do magazynów danych, takich jak rejestr i magazyn certyfikatów, tak samo łatwo jak do systemu plików. PowerShell zawiera rozbudowany parser wyrażeń i w pełni rozwinięty język skryptowy.
PowerShell jest oprogramowaniem open source. Zobacz https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Wersja: ___VERSION___
Dziennik zmian: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Interaktywna powłoka</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Język skryptowy</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Zarządzanie zdalne</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Interpretador de comandos</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Linha de Comando</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Automação</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Automação de Tarefas</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Scripts</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell é um shell de linha de comando baseado em tarefas e uma linguagem de script criada no .NET. O PowerShell ajuda administradores de sistemas e usuários avançados a automatizar rapidamente tarefas que gerenciam sistemas operacionais (Linux, macOS e Windows) e processos.
Os comandos do PowerShell permitem gerenciar computadores pela linha de comando. Os provedores do PowerShell permitem acessar repositórios de dados, como o Registro e o repositório de certificados, com a mesma facilidade com que você acessa o sistema de arquivos. O PowerShell inclui um avançado analisador de expressões e uma linguagem de script totalmente desenvolvida.
O PowerShell é de código aberto. Confira https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Versão: ___VERSION___
Log de Mudanças: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Shell Interativo</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Linguagem de Script</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Gerenciamento Remoto</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Оболочка</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Терминал</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Командная строка</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Служба автоматизации</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Автоматизация задач</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Создание скрипта</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell — это оболочка командной строки с поддержкой задач и язык скриптов на основе .NET. PowerShell позволяет системным администраторам и опытным пользователям быстро автоматизировать задачи для управления процессами и операционными системами (Linux, macOS и Windows).
Команды PowerShell позволяют управлять компьютерами из командной строки. При использовании поставщиков PowerShell доступ к хранилищам данных, таким как реестр и хранилище сертификатов, становится таким же простым, как и доступ к файловой системе. PowerShell включает многофункциональное средство синтаксического анализа выражений и полностью разработанный язык скриптов.
PowerShell использует открытый код. См. https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Версия: ___VERSION___
Журнал изменений: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Интерактивная оболочка</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Язык сценариев</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Удаленное управление</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Корпорация Майкрософт</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Kabuk</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->Windows PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->Terminal</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->Komut Satırı</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->Otomasyon</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->Görev Otomasyonu</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->Betik Yazma</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->Windows PowerShell, .NET üzerine oluşturulmuş görev tabanlı bir komut satırı kabuğu ve betik dilidir. Windows PowerShell, sistem yöneticilerinin ve ileri düzey kullanıcıların işletim sistemlerini (Linux, macOS ve Windows) ve süreçleri yöneten görevleri hızla otomatikleştirmelerine yardımcı olur.
Windows PowerShell komutları, bilgisayarları komut satırından yönetmenizi sağlar. Windows PowerShell sağlayıcıları, kayıt defteri ve sertifika deposu gibi veri depolarına, dosya sistemine eriştiğiniz kadar kolay erişmenizi sağlar. Windows PowerShell, zengin bir ifade ayrıştırıcısı ve tam gelişmiş bir betik dili içerir.
Windows PowerShell Açık Kaynaktır. Daha fazla bilgi için https://github.com/powershell/powershell adresine bakın </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->Sürüm: ___VERSION___
Değişiklik günlüğü: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->Etkileşimli Kabuk</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->Betik Dili</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->Uzaktan Yönetim</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->终端</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->命令行</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->自动化</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->任务自动化</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->脚本</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell 是基于 .NET 构建的基于任务的命令行 shell 和脚本语言。 PowerShell 可帮助系统管理员和高级用户快速自动执行用于管理操作系统(Linux、macOS 和 Windows)和进程的任务。
使用 PowerShell 命令,可以通过命令行管理计算机。 借助 PowerShell 提供程序,可以访问像访问文件系统一样方便地访问数据存储(如注册表和证书存储)。 PowerShell 具有丰富的表达式分析器和充分开发的脚本语言。
PowerShell 是开放源代码。 请参阅 https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->版本: ___VERSION___
更改日志: ___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->交互式 Shell</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->脚本语言</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->远程管理</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
+130
View File
@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ProductDescription language="en-us" xmlns="http://schemas.microsoft.com/appx/2012/ProductDescription" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:lang="en-us" Release="">
<Keywords>
<!-- Valid length: 30 character limit, up to 7 elements -->
<Keyword _locID="App_keyword1">
<!-- _locComment_text="{MaxLength=30} App keyword 1" -->Shell</Keyword>
<Keyword _locID="App_keyword2">
<!-- _locComment_text="{MaxLength=30} App keyword 2" -->PowerShell</Keyword>
<Keyword _locID="App_keyword3">
<!-- _locComment_text="{MaxLength=30} App keyword 3" -->終端機</Keyword>
<Keyword _locID="App_keyword4">
<!-- _locComment_text="{MaxLength=30} App keyword 4" -->命令列</Keyword>
<Keyword _locID="App_keyword5">
<!-- _locComment_text="{MaxLength=30} App keyword 5" -->自動化</Keyword>
<Keyword _locID="App_keyword6">
<!-- _locComment_text="{MaxLength=30} App keyword 6" -->工作自動化</Keyword>
<Keyword _locID="App_keyword7">
<!-- _locComment_text="{MaxLength=30} App keyword 7" -->指令碼處理</Keyword>
</Keywords>
<Description _locID="App_Description">
<!-- _locComment_text="{MaxLength=10000} {Locked=Windows} App Description" -->PowerShell 是工作型命令列殼層與指令碼語言,並建置在 .NET 之上。 PowerShell 可協助系統管理員與進階使用者快速地將管理作業系統 (Linux、macOS 與 Windows) 與處理序的工作自動化。
PowerShell 命令可讓您從命令列管理電腦。 PowerShell 提供者可讓您如同存取檔案系統般輕易地存取資料存放區 (例如登錄與憑證存放區)。 PowerShell 包含豐富的運算式剖析器與完整開發的指令碼語言。
PowerShell 是開放原始碼。 請參閱 https://github.com/powershell/powershell </Description>
<ShortDescription _locID="App_ShortDescription">
<!-- Only used for games. This description appears in the Information section of the Game Hub on Xbox One, and helps customers understand more about your game. -->
<!-- _locComment_text="{MaxLength=500} App ShortDescription" -->
</ShortDescription>
<ShortTitle _locID="App_ShortTitle">
<!-- A shorter version of your product's name. If provided, this shorter name may appear in various places on Xbox One (during installation, in Achievements, etc.) in place of the full title of your product. -->
<!-- _locComment_text="{MaxLength=50} App ShortTitle" -->
</ShortTitle>
<SortTitle _locID="App_SortTitle">
<!-- If your product could be alphabetized in different ways, you can enter another version here. This may help customers find the product more quickly when searching. -->
<!-- _locComment_text="{MaxLength=255} App SortTitle" -->
</SortTitle>
<VoiceTitle _locID="App_VoiceTitle">
<!-- An alternate name for your product that, if provided, may be used in the audio experience on Xbox One when using Kinect or a headset. -->
<!-- _locComment_text="{MaxLength=255} App VoiceTitle" -->
</VoiceTitle>
<DevStudio _locID="App_DevStudio">
<!-- Specify this value if you want to include a "Developed by" field in the listing. (The "Published by" field will list the publisher display name associated with your account, whether or not you provide a devStudio value.) -->
<!-- _locComment_text="{MaxLength=255} App DevStudio" -->
</DevStudio>
<ReleaseNotes _locID="App_ReleaseNotes">
<!-- _locComment_text="{MaxLength=1500} {Locked=___VERSION___}{Locked=___CHANGELOGLINK___} App Release Note" -->版本: ___VERSION___
變更記錄:___CHANGELOGLINK___</ReleaseNotes>
<AppFeatures>
<!-- Valid length: 200 character limit, up to 20 elements -->
<AppFeature _locID="App_feature1">
<!-- _locComment_text="{MaxLength=200} App Feature 1" -->互動式殼層</AppFeature>
<AppFeature _locID="App_feature2">
<!-- _locComment_text="{MaxLength=200} App Feature 2" -->指令碼語言</AppFeature>
<AppFeature _locID="App_feature3">
<!-- _locComment_text="{MaxLength=200} App Feature 3" -->遠端管理</AppFeature>
<AppFeature _locID="App_feature4">
<!-- _locComment_text="{MaxLength=200} App Feature 4" -->
</AppFeature>
<AppFeature _locID="App_feature5">
<!-- _locComment_text="{MaxLength=200} App Feature 5" -->
</AppFeature>
<AppFeature _locID="App_feature6">
<!-- _locComment_text="{MaxLength=200} App Feature 6" -->
</AppFeature>
<AppFeature _locID="App_feature7">
<!-- _locComment_text="{MaxLength=200} App Feature 7" -->
</AppFeature>
<AppFeature _locID="App_feature8">
<!-- _locComment_text="{MaxLength=200} App Feature 8" -->
</AppFeature>
<AppFeature _locID="App_feature9">
<!-- _locComment_text="{MaxLength=200} App Feature 9" -->
</AppFeature>
<AppFeature _locID="App_feature10">
<!-- _locComment_text="{MaxLength=200} App Feature 10" -->
</AppFeature>
<AppFeature _locID="App_feature11">
<!-- _locComment_text="{MaxLength=200} App Feature 11" -->
</AppFeature>
<AppFeature _locID="App_feature12">
<!-- _locComment_text="{MaxLength=200} App Feature 12" -->
</AppFeature>
<AppFeature _locID="App_feature13">
<!-- _locComment_text="{MaxLength=200} App Feature 13" -->
</AppFeature>
<AppFeature _locID="App_feature14">
<!-- _locComment_text="{MaxLength=200} App Feature 14" -->
</AppFeature>
<AppFeature _locID="App_feature15">
<!-- _locComment_text="{MaxLength=200} App Feature 15" -->
</AppFeature>
<AppFeature _locID="App_feature16">
<!-- _locComment_text="{MaxLength=200} App Feature 16" -->
</AppFeature>
<AppFeature _locID="App_feature17">
<!-- _locComment_text="{MaxLength=200} App Feature 17" -->
</AppFeature>
<AppFeature _locID="App_feature18">
<!-- _locComment_text="{MaxLength=200} App Feature 18" -->
</AppFeature>
<AppFeature _locID="App_feature19">
<!-- _locComment_text="{MaxLength=200} App Feature 19" -->
</AppFeature>
<AppFeature _locID="App_feature20">
<!-- _locComment_text="{MaxLength=200} App Feature 20" -->
</AppFeature>
</AppFeatures>
<RecommendedHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
<Recommendation _locID="App_RecommendedHW1">
<!-- _locComment_text="{MaxLength=200} App Recommended Hardware 1" -->
</Recommendation>
</RecommendedHardware>
<MinimumHardware>
<!-- Valid length: 200 character limit, up to 11 elements -->
</MinimumHardware>
<CopyrightAndTrademark _locID="App_CopyrightandTrademark">
<!-- _locComment_text="{MaxLength=200} Copyright and Trademark" -->Microsoft Corporation</CopyrightAndTrademark>
<AdditionalLicenseTerms _locID="App_AdditionalLicenseTerms">
<!-- _locComment_text="{MaxLength=10000} Additional License Terms" -->
</AdditionalLicenseTerms>
<WebsiteURL _locID="App_WebsiteURL">
<!-- _locComment_text="{MaxLength=2048} WebsiteURL" -->https://github.com/PowerShell/PowerShell</WebsiteURL>
<SupportContactInfo _locID="App_SupportContactInfo">
<!-- _locComment_text="{MaxLength=2048} Support Contact Info" -->https://github.com/PowerShell/PowerShell/issues</SupportContactInfo>
<PrivacyPolicyURL _locID="App_PrivacyURL">
<!-- _locComment_text="{MaxLength=2048} Privacy Policy URL" -->https://go.microsoft.com/fwlink/?LinkID=521839</PrivacyPolicyURL>
</ProductDescription>
-2
View File
@@ -14,8 +14,6 @@
"qps-ploca",
"qps-plocm"
],
"MediaRootPath": "",
"MediaFallbackLanguage": "en-US",
"PackagePath": [],
"OutPath": "",
"OutName": "",
+34 -6
View File
@@ -54,12 +54,28 @@ jobs:
parameters:
repoRoot: '$(repoRoot)'
- task: UseDotNet@2
displayName: 'Use .NET Core sdk'
inputs:
useGlobalJson: true
packageType: 'sdk'
workingDirectory: $(Build.SourcesDirectory)"
- template: ../install-dotnet.yml
parameters:
architecture: win-x64
- pwsh: |
$sdkVersion = $env:DOTNET_SDK_VERSION
if ([string]::IsNullOrWhiteSpace($sdkVersion)) {
throw 'DOTNET_SDK_VERSION must be specified for an early access build.'
}
$sdkVersion = $sdkVersion.Trim()
$globalJsonPath = Join-Path '$(repoRoot)' 'global.json'
$globalJson = Get-Content -Path $globalJsonPath -Raw | ConvertFrom-Json
$globalJson.sdk.version = $sdkVersion
$globalJson | ConvertTo-Json -Depth 10 | Set-Content -Path $globalJsonPath
Write-Verbose -Verbose "Updated global.json to use .NET SDK $sdkVersion."
displayName: Select early access .NET SDK
condition: eq(variables['ISEARLYACCESS'], 'true')
env:
DOTNET_SDK_VERSION: $(DOTNET_SDK_VERSION)
ob_restore_phase: true
- pwsh: |
Import-Module .\build.psm1 -force
@@ -70,12 +86,17 @@ jobs:
displayName: Install dotnet-symbol
workingDirectory: '$(repoRoot)'
retryCountOnTaskFailure: 2
env:
ob_restore_phase: true
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- task: CodeQL3000Init@0 # Add CodeQL Init task right before your 'Build' step.
displayName: 🔏 CodeQL 3000 Init
condition: eq(variables['CODEQL_ENABLED'], 'true')
inputs:
Language: csharp
env:
ob_restore_phase: true
- pwsh: |
Import-Module .\build.psm1 -force
@@ -98,6 +119,9 @@ jobs:
Copy-Item -Path "$OutputFolder\*" -Destination $Destination -Recurse -Verbose
workingDirectory: '$(repoRoot)'
displayName: 'Build PowerShell Source'
env:
ob_restore_phase: true
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- pwsh: |
# Only keep windows runtimes
@@ -120,10 +144,14 @@ jobs:
Write-Host
workingDirectory: '$(repoRoot)'
displayName: 'Remove unused runtimes'
env:
ob_restore_phase: true
- task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step.
displayName: 🔏 CodeQL 3000 Finalize
condition: eq(variables['CODEQL_ENABLED'], 'true')
env:
ob_restore_phase: true
- pwsh: |
Get-ChildItem -Path env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
@@ -4,8 +4,6 @@
parameters:
- name: parentJobs
type: jobList
- name: SkipVerifyPackages
type: boolean
jobs:
- job: generateNotice
@@ -55,12 +53,7 @@ jobs:
- task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0
displayName: 'Component Detection'
inputs:
sourceScanPath: '$(repoRoot)\tools'
- pwsh: |
$(repoRoot)/tools/clearlyDefined/ClearlyDefined.ps1 -TestAndHarvest
displayName: Verify that packages have license data
condition: eq(${{ parameters.SkipVerifyPackages }}, false)
sourceScanPath: '$(repoRoot)\tools\cgmanifest\tpn'
- task: msospo.ospo-extension.8d7f9abb-6896-461d-9e25-4f74ed65ddb2.notice@0
displayName: 'NOTICE File Generator'
@@ -0,0 +1,178 @@
parameters:
- name: Channel
type: string
- name: createVPack
type: boolean
jobs:
- job: Bundle_${{ parameters.Channel }}
condition: contains(variables['EnabledChannels'], '${{ parameters.Channel }}')
pool:
type: windows
variables:
ArtifactPlatform: 'windows'
Channel: ${{ parameters.Channel }}
ob_outputDirectory: '$(BUILD.SOURCESDIRECTORY)\out'
ob_artifactBaseName: 'drop_pack_$(Channel)'
ob_createvpack_enabled: ${{ parameters.createVPack }}
ob_createvpack_packagename: 'PowerShell7-$(Channel).Store.app'
ob_createvpack_owneralias: 'dongbow'
ob_createvpack_description: 'VPack for the PowerShell 7 Store Application ($(Channel))'
ob_createvpack_targetDestinationDirectory: '$(Destination)' ## The value is from the 'CreateVpack' task, used when pulling the generated VPack.
ob_createvpack_propsFile: false
ob_createvpack_provData: true
ob_createvpack_metadata: '$(Build.SourceVersion)'
ob_createvpack_versionAs: string
ob_createvpack_version: '$(Version)'
ob_createvpack_verbose: true
steps:
- checkout: self
displayName: Checkout source code - during restore
clean: true
path: s ## $(Build.SourcesDirectory) is at '$(Pipeline.Workspace)\s', so we need to check out repo to the 's' folder.
env:
ob_restore_phase: true
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: no
- template: /.pipelines/templates/shouldSign.yml@self
- task: DownloadPipelineArtifact@2
inputs:
artifactName: drop_build_x64
itemPattern: |
**/*.msix
targetPath: '$(Build.ArtifactStagingDirectory)\downloads'
displayName: Download msix for x64
- task: DownloadPipelineArtifact@2
inputs:
artifactName: drop_build_arm64
itemPattern: |
**/*.msix
targetPath: '$(Build.ArtifactStagingDirectory)\downloads'
displayName: Download msix for arm64
# Finds the makeappx tool on the machine.
- pwsh: |
Write-Verbose -Verbose 'PowerShell Version: $(Version)'
$cmd = Get-Command makeappx.exe -ErrorAction Ignore
if ($cmd) {
Write-Verbose -Verbose 'makeappx available in PATH'
$exePath = $cmd.Source
} else {
$makeappx = Get-ChildItem -Recurse 'C:\Program Files (x86)\Windows Kits\10\makeappx.exe' |
Where-Object { $_.DirectoryName -match 'x64' } |
Select-Object -Last 1
$exePath = $makeappx.FullName
Write-Verbose -Verbose "makeappx was found: $exePath"
}
$vstsCommandString = "vso[task.setvariable variable=MakeAppxPath]$exePath"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
displayName: Find makeappx tool
retryCountOnTaskFailure: 1
- pwsh: |
$sourceDir = '$(Pipeline.Workspace)\releasePipeline\msix'
$null = New-Item -Path $sourceDir -ItemType Directory -Force
$channel = '$(Channel)'
if ($channel -eq 'LTS') {
Write-Verbose -Verbose "LTS channel. Remove Stable MSIX packages"
$stablePkgs = Get-ChildItem -Path "$(Build.ArtifactStagingDirectory)\downloads\*.msix" -Recurse |
Where-Object { $_.FullName -notlike '*-LTS-*.msix' } | ForEach-Object FullName
if ($stablePkgs) {
Remove-Item -Path $stablePkgs -Force -Verbose -ErrorAction Stop
} else {
Write-Verbose -Verbose "No Stable MSIX package was found."
}
}
else {
Write-Verbose -Verbose "Stable channel. Remove LTS MSIX packages"
$ltsPkgs = Get-ChildItem -Path "$(Build.ArtifactStagingDirectory)\downloads\*.msix" -Recurse |
Where-Object { $_.FullName -like '*-LTS-*.msix' } | ForEach-Object FullName
if ($ltsPkgs) {
Remove-Item -Path $ltsPkgs -Force -Verbose -ErrorAction Stop
} else {
Write-Verbose -Verbose "No LTS MSIX package was found."
}
}
$msixFiles = Get-ChildItem -Path "$(Build.ArtifactStagingDirectory)\downloads\*.msix" -Recurse
foreach ($msixFile in $msixFiles) {
$null = Copy-Item -Path $msixFile.FullName -Destination $sourceDir -Force -Verbose
}
$file = Get-ChildItem $sourceDir | Select-Object -First 1
$prefix = ($file.BaseName -split "-win")[0]
$pkgName = "$prefix.msixbundle"
Write-Verbose -Verbose "Creating $pkgName"
$makeappx = '$(MakeAppxPath)'
$outputDir = "$sourceDir\output"
New-Item $outputDir -Type Directory -Force > $null
& $makeappx bundle /d $sourceDir /p "$outputDir\$pkgName"
if ($LASTEXITCODE -ne 0) {
throw "makeappx bundle failed with exit code $LASTEXITCODE"
}
Get-ChildItem -Path $sourceDir -Recurse | Out-String -Width 200
$vstsCommandString = "vso[task.setvariable variable=BundleDir]$outputDir"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
displayName: Create MsixBundle
retryCountOnTaskFailure: 1
- task: onebranch.pipeline.signing@1
displayName: Sign MsixBundle
inputs:
command: 'sign'
signing_profile: $(MSIXProfile)
files_to_sign: '**/*.msixbundle'
search_root: '$(BundleDir)'
- pwsh: |
$signedBundle = Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File
Write-Verbose -Verbose "Signed bundle: $signedBundle"
$signature = Get-AuthenticodeSignature -FilePath $signedBundle.FullName
if ($signature.Status -ne 'Valid') {
throw "The bundle file doesn't have a valid signature. Signature status: $($signature.Status)"
}
if (-not (Test-Path '$(ob_outputDirectory)' -PathType Container)) {
$null = New-Item '$(ob_outputDirectory)' -ItemType Directory -ErrorAction Stop
}
$channel = '$(Channel)'
$targetFileName = if ($channel -eq 'LTS') {
'Microsoft.PowerShell-LTS_8wekyb3d8bbwe.msixbundle'
} else {
'Microsoft.PowerShell_8wekyb3d8bbwe.msixbundle'
}
$targetPath = Join-Path '$(ob_outputDirectory)' $targetFileName
Copy-Item -Verbose -Path $signedBundle.FullName -Destination $targetPath
Write-Verbose -Verbose "Uploaded Bundle:"
Get-ChildItem -Path $(ob_outputDirectory) | Out-String -Width 200 -Stream | Write-Verbose -Verbose
displayName: 'Stage msixbundle for VPack'
- pwsh: |
Write-Verbose "VPack enabled: $(ob_createvpack_enabled)" -Verbose
Write-Verbose "VPack Name: $(ob_createvpack_packagename)" -Verbose
Write-Verbose "VPack Version: $(ob_createvpack_version)" -Verbose
$vpackFiles = Get-ChildItem -Path '$(ob_outputDirectory)\*' -Recurse
if($vpackFiles.Count -eq 0) {
throw "No files found in $(ob_outputDirectory)"
}
$vpackFiles | Out-String -Width 200
displayName: Debug Output Directory and Version
@@ -0,0 +1,61 @@
parameters:
- name: DotnetRuntimeVersion
type: string
- name: DotnetSdkVersion
type: string
jobs:
- job: download_dotnet_early_access
displayName: Download DotNet Early Access
variables:
- group: dotnet-early-access
- name: DOTNET_RUNTIME_VERSION
value: ${{ parameters.DotnetRuntimeVersion }}
- name: DOTNET_SDK_VERSION
value: ${{ parameters.DotnetSdkVersion }}
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/pkgs'
- name: destinationPath
value: '$(ob_outputDirectory)'
pool:
name: PowerShell1ES
type: windows
isCustom: true
demands:
- ImageOverride -equals PSMMS2019-Secure
steps:
- checkout: self
clean: true
- pwsh: |
Get-ChildItem Env: | Out-String -Width 9999 -Stream | Write-Verbose -Verbose
displayName: Capture environment
- task: AzurePowerShell@5
inputs:
azureSubscription: powershell-net-early-access
azurePowerShellVersion: LatestVersion
ScriptType: InlineScript
pwsh: true
inline: |
$DOTNET_PRIVATE_SAS = Get-AzKeyVaultSecret -VaultName $env:DOTNET_AZ_KV_NAME -Name $env:DOTNET_AZ_SECRET_NAME -AsPlainText
Write-Verbose -Message "DOTNET_PRIVATE_SAS acquired" -Verbose
Import-Module "$env:BUILD_SOURCESDIRECTORY/build.psm1" -Force
if (-not (Test-Path '$(destinationPath)'))
{
New-Item -ItemType Directory -Path '$(destinationPath)' -Force -Verbose | Out-Null
}
Get-DotnetEarlyAccess -DestinationPath '$(destinationPath)' -Architecture all -DOTNET_PRIVATE_SAS $DOTNET_PRIVATE_SAS
Get-ChildItem -Path '$(destinationPath)' -Recurse | ForEach-Object {
Write-Verbose -verbose "Uploading $($_.FullName) to 'dotnet-packages'"
Write-Host "##vso[artifact.upload containerfolder=dotnet-packages;artifactname=dotnet-packages]$($_.FullName)"
}
displayName: 'Download DotNet Early Access'
@@ -16,8 +16,20 @@ steps:
$configPath = "${env:NugetConfigDir}/nuget.config"
Import-Module ${{ parameters.repoRoot }}/build.psm1 -Force
Write-Verbose -Verbose "Running: Switch-PSNugetConfig -Source Private -UserName '$(AzDevopsFeedUserNameKVPAT)' -ClearTextPAT '$(powershellPackageReadPat)'"
Switch-PSNugetConfig -Source Private -UserName '$(AzDevopsFeedUserNameKVPAT)' -ClearTextPAT '$(powershellPackageReadPat)'
$earlyAccess = $env:ISEARLYACCESS -eq 'true'
Write-Verbose -Verbose "Is Early access: $earlyAccess"
if (-not $earlyAccess)
{
Write-Verbose -Verbose "Running: Switch-PSNugetConfig -Source Private -UserName '$(AzDevopsFeedUserNameKVPAT)' -ClearTextPAT '$(powershellPackageReadPat)'"
Switch-PSNugetConfig -Source Private -UserName '$(AzDevopsFeedUserNameKVPAT)' -ClearTextPAT '$(powershellPackageReadPat)'
}
else
{
Write-Verbose -Verbose "Running: Switch-PSNugetConfig -Source EarlyAccess (using Azure DevOps feed credentials from pipeline variables)"
Switch-PSNugetConfig -Source EarlyAccess -UserName '$(AzDevopsFeedUserNameKVPAT)' -ClearTextPAT '$(powershellPackageReadPat)'
}
if(-not (Test-Path $configPath))
{
@@ -34,6 +46,61 @@ steps:
NugetConfigDir: ${{ parameters.repoRoot }}/src/Modules
ob_restore_phase: ${{ parameters.ob_restore_phase }}
- task: AzureCLI@2
inputs:
azureSubscription: powershell-net-early-access
scriptType: pscore
scriptLocation: inlineScript
inlineScript: |
Write-Verbose -Verbose "Getting an Azure DevOps access token"
# Microsoft's well-known Entra resource ID for the Azure DevOps token audience.
$azureDevOpsResourceUrl = '499b84ac-1321-427f-aa17-267ca6975798'
$azt = az account get-access-token --resource $azureDevOpsResourceUrl --query accessToken --output tsv
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($azt)) {
throw "Failed to get an Azure DevOps access token."
}
Write-Host "##vso[task.setsecret]$azt"
Write-Verbose -Verbose "Setting up Azure Artifacts Credential Provider token"
$earlyAccessFeed = '$(EARLY_ACCESS_FEED)'
$ADORepoUri = switch ($earlyAccessFeed) {
'net8' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-8-early-access/nuget/v3/index.json' }
'net9' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-9-early-access/nuget/v3/index.json' }
'net10' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-10-early-access/nuget/v3/index.json' }
'net11' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-11-early-access/nuget/v3/index.json' }
default { throw "Unknown early access feed URL: $earlyAccessFeed" }
}
$powerShellRepoUri = 'https://pkgs.dev.azure.com/powershell/PowerShell/_packaging/PowerShell/nuget/v3/index.json'
Write-Verbose -Verbose "ADORepoUri == $ADORepoUri"
if ([string]::IsNullOrEmpty($ADORepoUri) -eq $false)
{
$endpointCredsObj = @{ endpointCredentials = @(
@{ endpoint = $ADORepoUri; password = $azt }
@{
endpoint = $powerShellRepoUri
username = '$(AzDevopsFeedUserNameKVPAT)'
password = '$(powershellPackageReadPat)'
}
)}
$VSS_NUGET_EXTERNAL_FEED_ENDPOINTS = $endpointCredsObj | ConvertTo-Json -Compress
Write-Verbose -Verbose "Setting VSS_NUGET_EXTERNAL_FEED_ENDPOINTS environment variable"
Write-Host "##vso[task.setvariable variable=VSS_NUGET_EXTERNAL_FEED_ENDPOINTS;issecret=true]$VSS_NUGET_EXTERNAL_FEED_ENDPOINTS"
}
else
{
Write-Verbose -Verbose "EARLY_ACCESS_FEED_URL is not set"
}
displayName: 'Setup Azure Artifacts Credential Provider secret'
condition: eq(variables['ISEARLYACCESS'], 'true')
env:
ob_restore_phase: ${{ parameters.ob_restore_phase }}
- pwsh: |
Get-ChildItem ${{ parameters.repoRoot }}/nuget.config -Recurse | Foreach-Object {
Write-Verbose -Verbose "--- START $($_.fullname) ---"
+76
View File
@@ -2,6 +2,19 @@ parameters:
- name: ob_restore_phase
type: boolean
default: true
- name: architecture
type: string
default: 'win-x64'
values:
- 'win-x64'
- 'win-x86'
- 'win-arm64'
- 'linux-x64'
- 'linux-arm64'
- 'linux-musl-x64'
- 'linux-musl-arm64'
- 'osx-x64'
- 'osx-arm64'
steps:
- pwsh: |
@@ -19,6 +32,69 @@ steps:
displayName: 'Install dotnet SDK'
workingDirectory: $(RepoRoot)
condition: and(ne(variables['ISEARLYACCESS'], 'true'), ne(variables['ISEARLYACCESS'], 'True'))
env:
ob_restore_phase: ${{ parameters.ob_restore_phase }}
- task: DownloadPipelineArtifact@2
displayName: "Download dotnet-packages artifact"
condition: eq(variables['ISEARLYACCESS'], 'true')
inputs:
artifactName: 'dotnet-packages'
targetPath: '$(Pipeline.Workspace)/dotnet-packages'
env:
ob_restore_phase: ${{ parameters.ob_restore_phase }}
- pwsh: |
$arch = '${{ parameters.architecture }}'
$sdkFilePattern = "dotnet-sdk-*-${arch}.*"
if (-not (Test-Path '$(Pipeline.Workspace)/dotnet-packages')) {
New-Item -Path '$(Pipeline.Workspace)/dotnet-packages' -ItemType Directory -Force -Verbose | Out-Null
}
$filePath = Get-ChildItem '$(Pipeline.Workspace)/dotnet-packages' -Recurse -File | Where-Object { $_.Name -like $sdkFilePattern } | Select-Object -First 1 -ExpandProperty FullName
if (-not $filePath) {
Get-ChildItem -Path '$(Pipeline.Workspace)/dotnet-packages' -Recurse
throw "SDK file matching pattern $sdkFilePattern not found in $(Pipeline.Workspace)/dotnet-packages"
}
$dotnetLocation = if ($IsWindows) { "$env:LocalAppData\Microsoft\dotnet" } else { "$env:HOME/.dotnet" }
if (-not (Test-Path $dotnetLocation)) {
New-Item -ItemType Directory -Path $dotnetLocation -Force -Verbose | Out-Null
}
Write-Verbose -Verbose "Extracting SDK from $filePath to $dotnetLocation"
if ($filePath -match '\.(tar\.gz|tgz)$') {
& tar -xzf $filePath -C $dotnetLocation
if ($LASTEXITCODE -ne 0) {
throw "Failed to extract $filePath with tar (exit code $LASTEXITCODE)"
}
} elseif ($filePath -match '\.zip$') {
Expand-Archive -Path $filePath -DestinationPath $dotnetLocation -Force
} else {
throw "Unsupported SDK archive format: $filePath"
}
Write-Verbose -Verbose "Expand dotnet package complete."
$dotnetExe = if ($IsWindows) {
"$dotnetLocation\dotnet.exe"
} else {
"$dotnetLocation/dotnet"
}
if (-not (Test-Path $dotnetExe)) {
throw "dotnet executable not found at $dotnetExe"
}
Get-ChildItem -Path $dotnetLocation -Recurse
& $dotnetExe --info
workingDirectory: $(RepoRoot)
displayName: Install dotnet early access
condition: eq(variables['ISEARLYACCESS'], 'true')
env:
ob_restore_phase: ${{ parameters.ob_restore_phase }}
+30 -9
View File
@@ -1,9 +1,9 @@
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedeDrop: 'drop_linux_sign_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: deb
jobName: 'deb'
signingProfile: 'CP-450779-pgpdetached'
dotnetArch: 'linux-x64'
jobs:
- job: ${{ parameters.jobName }}
@@ -20,6 +20,7 @@ jobs:
- name: skipNugetSecurityAnalysis
value: true
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_binskim_enabled
@@ -34,8 +35,16 @@ jobs:
value: $(Build.SourcesDirectory)/PowerShell/.config/tsaoptions.json
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)/PowerShell/.config/suppress.json
- name: SigningProfile
value: ${{ parameters.signingProfile }}
# PGP signing profile selection: Mariner (Azure Linux) packages ship through
# a different distribution channel and must be signed with the Mariner release
# key; all other Linux packages use the standard PowerShell Linux key. Both
# key codes come from the `certificate_logical_to_actual` variable group.
- ${{ if startsWith(parameters.jobName, 'mariner') }}:
- name: SigningProfile
value: $(pgp_release_cert_id)
- ${{ else }}:
- name: SigningProfile
value: $(pgp_linux_cert_id)
steps:
- checkout: self
@@ -87,6 +96,8 @@ jobs:
ob_restore_phase: true # This ensures this done in restore phase to workaround signing issue
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
architecture: ${{ parameters.dotnetArch }}
- pwsh: |
$packageType = '$(PackageType)'
@@ -124,10 +135,12 @@ jobs:
'tar' { 'Signed-linux-x64', 'powershell*.tar.gz' }
'tar-alpine-fxdependent' { 'Signed-fxdependent-noopt-linux-musl-x64', 'powershell*.tar.gz' }
'deb' { 'Signed-linux-x64', 'powershell*.deb' }
'deb-arm64' { 'Signed-linux-arm64', 'powershell*.deb' }
'rpm-fxdependent' { 'Signed-fxdependent-linux-x64', 'powershell*.rpm' }
'rpm-fxdependent-arm64' { 'Signed-fxdependent-linux-arm64', 'powershell*.rpm' }
'rpm' { 'Signed-linux-x64', 'powershell*.rpm' }
'min-size' { 'Signed-linux-x64', 'powershell*.tar.gz' }
'min-size-x64' { 'Signed-linux-x64', 'powershell*.tar.gz' }
'min-size-arm64' { 'Signed-linux-arm64', 'powershell*.tar.gz' }
}
$signedFilesPath = "$(Pipeline.Workspace)/CoOrdinatedBuildPipeline/${signedDrop}/${signedFolder}"
@@ -155,10 +168,6 @@ jobs:
Write-Verbose -Verbose "LTS: $LTS"
if ($LTS) {
Write-Verbose -Message "LTS Release: $LTS"
}
if (-not (Test-Path $(ob_outputDirectory))) {
New-Item -ItemType Directory -Path $(ob_outputDirectory) -Force
}
@@ -168,6 +177,11 @@ jobs:
Start-PSPackage -Type $packageType -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath
if ($LTS -and ($packageType -like 'deb*' -or $packageType -like 'rpm*')) {
Write-Verbose -Message "LTS Release: $LTS" -Verbose
Start-PSPackage -Type $packageType -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS
}
$vstsCommandString = "vso[task.setvariable variable=PackageFilter]$pkgFilter"
Write-Host ("sending " + $vstsCommandString)
Write-Host "##$vstsCommandString"
@@ -191,6 +205,13 @@ jobs:
$pkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $pkgFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "pkgPath: $pkgPath"
Copy-Item -Path $pkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
if ($pkgPath -like '*.tar.gz') {
$entry = & tar -tzvf $pkgPath | Where-Object { $_ -match '\spwsh$' } | Select-Object -First 1
if ($entry -notmatch '^-..x') {
throw "pwsh is not executable in $pkgPath : $entry"
}
}
displayName: 'Copy artifacts to output directory'
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
+4
View File
@@ -2,6 +2,7 @@ parameters:
Runtime: 'linux-x64'
BuildConfiguration: 'release'
JobName: 'build_linux'
dotnetArch: 'linux-x64'
jobs:
- job: build_${{ parameters.JobName }}
@@ -63,6 +64,8 @@ jobs:
Language: csharp
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
architecture: ${{ parameters.dotnetArch }}
- pwsh: |
$runtime = $env:RUNTIME
@@ -108,6 +111,7 @@ jobs:
displayName: 'Build Linux - $(Runtime)'
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
ob_restore_phase: true # Set ob_restore_phase to run this step before '🔒 Setup Signing' step.
- task: CodeQL3000Finalize@0 # Add CodeQL Finalize task right after your 'Build' step.
+72 -14
View File
@@ -1,6 +1,7 @@
parameters:
parentJob: ''
buildArchitecture: x64
OfficialBuild: true
jobs:
- job: package_macOS_${{ parameters.buildArchitecture }}
@@ -22,6 +23,7 @@ jobs:
- name: skipNugetSecurityAnalysis
value: true
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_binskim_enabled
@@ -76,6 +78,15 @@ jobs:
# Diagnostics is not critical it passes every time it runs
continueOnError: true
- pwsh: |
$signatureParameters = @{
Path = "$(Pipeline.Workspace)/CoOrdinatedBuildPipeline/drop_macos_sign_${{ parameters.buildArchitecture }}/Signed-${{ parameters.buildArchitecture }}"
OfficialBuild = [System.Convert]::ToBoolean('${{ parameters.OfficialBuild }}')
EntitlementsPath = "$(Build.SourcesDirectory)/assets/macos-entitlements.plist"
}
& "$(Build.SourcesDirectory)/tools/packaging/Update-MacOSCodeSignature.ps1" @signatureParameters
displayName: 'Apply and verify Apple codesign on signed binaries'
- pwsh: |
# Add -SkipReleaseChecks as a mitigation to unblock release.
# macos-10.15 does not allow creating a folder under root. Hence, moving the folder.
@@ -102,6 +113,10 @@ jobs:
Restore-PSOptions -PSOptionsPath "$psoptionsPath"
Get-PSOptions | Write-Verbose -Verbose
if (-not (Test-Path "$repoRoot/tools/metadata.json")) {
throw "metadata.json not found in $repoRoot/tools"
}
$metadata = Get-Content "$repoRoot/tools/metadata.json" -Raw | ConvertFrom-Json
Write-Verbose -Verbose "metadata:"
@@ -120,14 +135,19 @@ jobs:
Write-Verbose -Verbose "LTS: $LTS"
if ($LTS) {
Write-Verbose -Message "LTS Release: $LTS"
Write-Verbose -Message "LTS Release: $LTS" -Verbose
}
Start-PSBootstrap -Scenario Package
$macosRuntime = "osx-$buildArch"
Start-PSPackage -Type osxpkg -SkipReleaseChecks -MacOSRuntime $macosRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$LTS
Start-PSPackage -Type osxpkg -SkipReleaseChecks -MacOSRuntime $macosRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath
if ($LTS) {
Start-PSPackage -Type osxpkg -SkipReleaseChecks -MacOSRuntime $macosRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS
}
$pkgNameFilter = "powershell-*$macosRuntime.pkg"
Write-Verbose -Verbose "Looking for pkg packages with filter: $pkgNameFilter in '$(Pipeline.Workspace)' to upload..."
$pkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $pkgNameFilter -Recurse -File
@@ -145,11 +165,20 @@ jobs:
foreach($t in $tarPkgPath) {
$file = $t.FullName
$entry = & tar -tzvf $file | Where-Object { $_ -match '\spwsh$' } | Select-Object -First 1
if ($entry -notmatch '^-..x') {
throw "pwsh is not executable in $file : $entry"
}
Write-Verbose -verbose "Uploading $file to macos-pkgs"
Write-Host "##vso[artifact.upload containerfolder=macos-pkgs;artifactname=macos-pkgs]$file"
}
$packageInfo = Get-MacOSPackageIdentifierInfo -Version '$(Version)' -LTS:$LTS
Write-Verbose -Verbose "BundleId: $($packageInfo.PackageIdentifier)"
Write-Host "##vso[task.setvariable variable=BundleId;isOutput=true]$($packageInfo.PackageIdentifier)"
displayName: 'Package ${{ parameters.buildArchitecture}}'
name: packageStep
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
@@ -161,6 +190,7 @@ jobs:
type: windows
variables:
- group: certificate_logical_to_actual
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_binskim_enabled
@@ -169,7 +199,8 @@ jobs:
value: $(Build.SourcesDirectory)/PowerShell/.config/suppress.json
- name: BuildArch
value: ${{ parameters.buildArchitecture }}
- group: mscodehub-macos-package-signing
- name: BundleId
value: $[ dependencies.package_macOS_${{ parameters.buildArchitecture }}.outputs['packageStep.BundleId'] ]
steps:
- download: current
@@ -207,32 +238,59 @@ jobs:
inline_operation: |
[
{
"KeyCode": "$(KeyCode)",
"KeyCode": "$(apple_cert_id)",
"OperationCode": "MacAppDeveloperSign",
"ToolName": "sign",
"ToolVersion": "1.0",
"Parameters": {
"Hardening": "Enable",
"OpusInfo": "http://microsoft.com"
"Hardening": "--options=runtime"
}
}
]
- task: onebranch.pipeline.signing@1
displayName: 'OneBranch Notarize Package'
inputs:
command: 'sign'
files_to_sign: '**/*-osx-*.zip'
search_root: '$(Pipeline.Workspace)'
inline_operation: |
[
{
"KeyCode": "$(apple_cert_id)",
"OperationCode": "MacAppNotarize",
"ToolName": "sign",
"ToolVersion": "1.0",
"Parameters": {
"BundleId": "$(BundleId)"
}
}
]
timeoutInMinutes: 120
- pwsh: |
$signedPkg = Get-ChildItem -Path $(Pipeline.Workspace) -Filter "*osx*.zip" -File
if (-not (Test-Path $(ob_outputDirectory))) {
$null = New-Item -Path $(ob_outputDirectory) -ItemType Directory
}
$expandDir = "$(Pipeline.Workspace)/pkgExpand"
$null = New-Item -Path $expandDir -ItemType Directory -Force
$signedPkg | ForEach-Object {
Write-Verbose -Verbose "Signed package zip: $_"
Expand-Archive -Path $_ -DestinationPath $expandDir -Verbose
}
if (-not (Test-Path $_)) {
throw "Package not found: $_"
}
# ESRP's signing pipeline nests the PKG inside a '<hash>.zip.unzipped' subfolder
$pkgFile = Get-ChildItem -Path $expandDir -Filter '*.pkg' -Recurse -File
if (-not $pkgFile) {
throw "Package not found in: $signedPkg"
}
if (-not (Test-Path $(ob_outputDirectory))) {
$null = New-Item -Path $(ob_outputDirectory) -ItemType Directory
}
Expand-Archive -Path $_ -DestinationPath $(ob_outputDirectory) -Verbose
$pkgFile | ForEach-Object {
Move-Item -Path $_ -Destination $(ob_outputDirectory) -Verbose
}
Write-Verbose -Verbose "Expanded pkg file:"
+93
View File
@@ -1,5 +1,6 @@
parameters:
buildArchitecture: 'x64'
dotnetArch: 'osx-x64'
jobs:
- job: build_macOS_${{ parameters.buildArchitecture }}
displayName: Build macOS ${{ parameters.buildArchitecture }}
@@ -39,6 +40,8 @@ jobs:
## We cross compile for arm64, so the arch is always x64
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
architecture: ${{ parameters.dotnetArch }}
- pwsh: |
Import-Module $(PowerShellRoot)/build.psm1 -Force
@@ -69,6 +72,14 @@ jobs:
$psOptPath = "$(OB_OUTPUTDIRECTORY)/psoptions.json"
Save-PSOptions -PSOptionsPath $psOptPath
$entitlements = "$(PowerShellRoot)/assets/macos-entitlements.plist"
$pwshBin = "$(OB_OUTPUTDIRECTORY)/pwsh"
Write-Verbose -Verbose "Applying entitlements to $pwshBin"
codesign --sign - --force --options runtime --entitlements $entitlements $pwshBin
if ($LASTEXITCODE -ne 0) {
throw "codesign failed with exit code $LASTEXITCODE"
}
# Since we are using custom pool for macOS, we need to use artifact.upload to publish the artifacts
Write-Host "##vso[artifact.upload containerfolder=$artifactName;artifactname=$artifactName]$(OB_OUTPUTDIRECTORY)"
@@ -76,6 +87,7 @@ jobs:
displayName: 'Build'
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- template: /.pipelines/templates/step/finalize.yml@self
@@ -144,4 +156,85 @@ jobs:
binPath: $(DropRootPath)
OfficialBuild: $(ps_official_build)
# Apple-sign the Mach-O binaries inside the signed output.
- pwsh: |
$signedDir = "$(ob_outputDirectory)/Signed-$(Runtime)"
$zipFile = "$(Pipeline.Workspace)/macho-$(BuildArchitecture).zip"
Compress-Archive -Path "$signedDir/*" -DestinationPath $zipFile -Force
displayName: Compress signed folder for Apple signing
- task: onebranch.pipeline.signing@1
displayName: Apple CodeSign Mach-O binaries
inputs:
command: 'sign'
files_to_sign: 'macho-$(BuildArchitecture).zip'
search_root: '$(Pipeline.Workspace)'
inline_operation: |
[
{
"KeyCode": "$(apple_cert_id)",
"OperationCode": "MacAppDeveloperSign",
"ToolName": "sign",
"ToolVersion": "1.0",
"Parameters": {
"Hardening": "--options=runtime"
}
}
]
- pwsh: |
$signedDir = "$(ob_outputDirectory)/Signed-$(Runtime)"
$zipFile = "$(Pipeline.Workspace)/macho-$(BuildArchitecture).zip"
Expand-Archive -Path $zipFile -DestinationPath $signedDir -Force -Verbose
displayName: Expand Apple-signed Mach-O binaries into signed output
- pwsh: |
$signedDir = "$(ob_outputDirectory)/Signed-$(Runtime)"
$officialBuild = [System.Convert]::ToBoolean('$(ps_official_build)')
$officialSignature = 'Developer ID Application: Microsoft Corporation'
$codeDirectoryMagic = [byte[]](0xfa, 0xde, 0x0c, 0x02)
$missing = @()
Get-ChildItem $signedDir -Recurse -Include 'pwsh', '*.dylib' | ForEach-Object {
$bytes = [System.IO.File]::ReadAllBytes($_.FullName)
$text = [System.Text.Encoding]::Latin1.GetString($bytes)
$hasOfficialSignature = $text.Contains($officialSignature)
$hasAdHocSignature = $false
if (-not $officialBuild -and -not $hasOfficialSignature) {
# The package stage runs codesign --verify; here the Windows signing job
# verifies that unofficial output contains an ad-hoc CodeDirectory.
for ($offset = 0; $offset -le $bytes.Length - 16; $offset++) {
if ($bytes[$offset] -eq $codeDirectoryMagic[0] -and
$bytes[$offset + 1] -eq $codeDirectoryMagic[1] -and
$bytes[$offset + 2] -eq $codeDirectoryMagic[2] -and
$bytes[$offset + 3] -eq $codeDirectoryMagic[3] -and
($bytes[$offset + 15] -band 0x02) -ne 0) {
$hasAdHocSignature = $true
break
}
}
}
if (-not $hasOfficialSignature -and ($officialBuild -or -not $hasAdHocSignature)) {
$missing += $_.FullName
$expectedSignature = if ($officialBuild) {
"'$officialSignature'"
} else {
'a Developer ID signature or ad-hoc CodeDirectory'
}
Write-Host "##[error]Missing $expectedSignature in $($_.FullName)"
} else {
$signatureDescription = if ($hasOfficialSignature) {
'a Developer ID signature'
} else {
'an ad-hoc CodeDirectory'
}
Write-Host "OK: $($_.FullName) contains $signatureDescription"
}
}
if ($missing.Count -gt 0) {
throw "The expected Apple signature was not found in $($missing.Count) file(s): $($missing -join ', ')"
}
displayName: 'Verify Apple signature on Mach-O binaries'
- template: /.pipelines/templates/step/finalize.yml@self
+10 -8
View File
@@ -23,6 +23,7 @@ jobs:
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- group: DotNetPrivateBuildAccess
- group: certificate_logical_to_actual
steps:
- checkout: self
@@ -117,13 +118,13 @@ jobs:
Start-PSBuild -Clean -Runtime linux-x64 -Configuration Release -ReleaseTag $(ReleaseTagVar)
$sharedModules | Foreach-Object {
$refFile = Get-ChildItem -Path "$(PowerShellRoot)\src\$_\obj\Release\net10.0\refint\$_.dll"
$refFile = Get-ChildItem -Path "$(PowerShellRoot)\src\$_\obj\Release\net11.0\refint\$_.dll"
Write-Verbose -Verbose "RefAssembly: $refFile"
Copy-Item -Path $refFile -Destination "$refAssemblyFolder\$_.dll" -Verbose
$refDoc = "$(PowerShellRoot)\src\$_\bin\Release\net10.0\$_.xml"
$refDoc = "$(PowerShellRoot)\src\$_\bin\Release\net11.0\$_.xml"
if (-not (Test-Path $refDoc)) {
Write-Warning "$refDoc not found"
Get-ChildItem -Path "$(PowerShellRoot)\src\$_\bin\Release\net10.0\" | Out-String | Write-Verbose -Verbose
Get-ChildItem -Path "$(PowerShellRoot)\src\$_\bin\Release\net11.0\" | Out-String | Write-Verbose -Verbose
}
else {
Copy-Item -Path $refDoc -Destination "$refAssemblyFolder\$_.xml" -Verbose
@@ -133,13 +134,13 @@ jobs:
Start-PSBuild -Clean -Runtime win7-x64 -Configuration Release -ReleaseTag $(ReleaseTagVar)
$winOnlyModules | Foreach-Object {
$refFile = Get-ChildItem -Path "$(PowerShellRoot)\src\$_\obj\Release\net10.0\refint\*.dll"
$refFile = Get-ChildItem -Path "$(PowerShellRoot)\src\$_\obj\Release\net11.0\refint\*.dll"
Write-Verbose -Verbose 'RefAssembly: $refFile'
Copy-Item -Path $refFile -Destination "$refAssemblyFolder\$_.dll" -Verbose
$refDoc = "$(PowerShellRoot)\src\$_\bin\Release\net10.0\$_.xml"
$refDoc = "$(PowerShellRoot)\src\$_\bin\Release\net11.0\$_.xml"
if (-not (Test-Path $refDoc)) {
Write-Warning "$refDoc not found"
Get-ChildItem -Path "$(PowerShellRoot)\src\$_\bin\Release\net10.0" | Out-String | Write-Verbose -Verbose
Get-ChildItem -Path "$(PowerShellRoot)\src\$_\bin\Release\net11.0" | Out-String | Write-Verbose -Verbose
}
else {
Copy-Item -Path $refDoc -Destination "$refAssemblyFolder\$_.xml" -Verbose
@@ -155,6 +156,7 @@ jobs:
displayName: Build reference assemblies
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- task: onebranch.pipeline.signing@1
displayName: Sign ref assemblies
@@ -208,7 +210,7 @@ jobs:
displayName: Sign nupkg files
inputs:
command: 'sign'
cp_code: 'CP-401405'
cp_code: '$(nuget_cert_id)'
files_to_sign: '**\*.nupkg'
search_root: '$(Pipeline.Workspace)\nupkg'
@@ -268,7 +270,7 @@ jobs:
displayName: Sign nupkg files
inputs:
command: 'sign'
cp_code: 'CP-401405'
cp_code: '$(nuget_cert_id)'
files_to_sign: '**\*.nupkg'
search_root: '$(Pipeline.Workspace)\globaltools'
+9 -2
View File
@@ -2,6 +2,8 @@ parameters:
binPath: '$(ob_outputDirectory)'
globalTool: 'false'
SigningProfile: 'external_distribution'
ThirdPartySigningProfile: '$(msft_3rd_party_cert_id)'
SignAllBinariesWithThirdPartyProfile: false
OfficialBuild: true
vPackScenario: false
@@ -106,7 +108,12 @@ steps:
$signatures = $dlls | Get-AuthenticodeSignature
$officialIssuerPattern = '^CN=(Microsoft Code Signing PCA|Microsoft Root Certificate Authority|Microsoft Corporation).*'
$testCert = '^CN=(Microsoft|TestAzureEngBuildCodeSign).*'
$missingSignatures = $signatures | Where-Object { $_.status -eq 'notsigned' -or $_.SignerCertificate.Issuer -notmatch $testCert -or $_.SignerCertificate.Issuer -notmatch $officialIssuerPattern} | select-object -ExpandProperty Path
$signAllBinaries = [System.Convert]::ToBoolean('${{ parameters.SignAllBinariesWithThirdPartyProfile }}')
if ($signAllBinaries) {
$missingSignatures = $signatures | Select-Object -ExpandProperty Path
} else {
$missingSignatures = $signatures | Where-Object { $_.status -eq 'notsigned' -or $_.SignerCertificate.Issuer -notmatch $testCert -or $_.SignerCertificate.Issuer -notmatch $officialIssuerPattern} | Select-Object -ExpandProperty Path
}
Write-Verbose -verbose "to be signed:`r`n $($missingSignatures | Out-String)"
@@ -134,7 +141,7 @@ steps:
displayName: Sign 3rd Party files
inputs:
command: 'sign'
signing_profile: $(msft_3rd_party_cert_id)
signing_profile: ${{ parameters.ThirdPartySigningProfile }}
files_to_sign: '**\*.dll;**\*.exe'
search_root: $(Pipeline.Workspace)/thirdPartyToBeSigned
+40 -185
View File
@@ -12,7 +12,6 @@ jobs:
variables:
- group: msixTools
- group: 'Azure Blob variable group'
- group: 'Store Publish Variables'
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- name: ob_sdl_tsa_configFile
@@ -85,17 +84,44 @@ jobs:
$null = Copy-Item -Path $msixFile.FullName -Destination $sourceDir -Force -Verbose
}
$file = Get-ChildItem $sourceDir | Select-Object -First 1
$prefix = ($file.BaseName -split "-win")[0]
$pkgName = "$prefix.msixbundle"
Write-Verbose -Verbose "Creating $pkgName"
$makeappx = '$(MakeAppxPath)'
$outputDir = "$sourceDir\output"
New-Item $outputDir -Type Directory -Force > $null
& $makeappx bundle /d $sourceDir /p "$outputDir\$pkgName"
Get-ChildItem -Path $sourceDir -Recurse
# Separate LTS and Stable/Preview MSIX files by filename convention
$ltsMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -match '-LTS-' })
$stableMsix = @(Get-ChildItem $sourceDir -Filter '*.msix' | Where-Object { $_.BaseName -notmatch '-LTS-' })
Write-Verbose -Verbose "Stable/Preview MSIX files: $($stableMsix.Name -join ', ')"
Write-Verbose -Verbose "LTS MSIX files: $($ltsMsix.Name -join ', ')"
# Create Stable/Preview bundle
if ($stableMsix.Count -gt 0) {
$stableDir = "$sourceDir\stable"
New-Item $stableDir -Type Directory -Force > $null
$stableMsix | Copy-Item -Destination $stableDir -Force
$file = $stableMsix | Select-Object -First 1
$prefix = ($file.BaseName -split "-win")[0]
$stableBundleName = "$prefix.msixbundle"
Write-Verbose -Verbose "Creating Stable/Preview bundle: $stableBundleName"
& $makeappx bundle /d $stableDir /p "$outputDir\$stableBundleName"
}
# Create LTS bundle
if ($ltsMsix.Count -gt 0) {
$ltsDir = "$sourceDir\lts"
New-Item $ltsDir -Type Directory -Force > $null
$ltsMsix | Copy-Item -Destination $ltsDir -Force
$file = $ltsMsix | Select-Object -First 1
$prefix = ($file.BaseName -split "-win")[0]
$ltsBundleName = "$prefix.msixbundle"
Write-Verbose -Verbose "Creating LTS bundle: $ltsBundleName"
& $makeappx bundle /d $ltsDir /p "$outputDir\$ltsBundleName"
}
Write-Verbose -Verbose "Created bundles:"
Get-ChildItem -Path $outputDir -Recurse
$vstsCommandString = "vso[task.setvariable variable=BundleDir]$outputDir"
Write-Host "sending " + $vstsCommandString
Write-Host "##$vstsCommandString"
@@ -112,188 +138,17 @@ jobs:
search_root: '$(BundleDir)'
- pwsh: |
$signedBundle = Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File
Write-Verbose -Verbose "Signed bundle: $signedBundle"
$signedBundles = @(Get-ChildItem -Path $(BundleDir) -Filter "*.msixbundle" -File)
Write-Verbose -Verbose "Signed bundles: $($signedBundles.Name -join ', ')"
if (-not (Test-Path $(ob_outputDirectory))) {
New-Item -ItemType Directory -Path $(ob_outputDirectory) -Force
}
Copy-Item -Path $signedBundle.FullName -Destination "$(ob_outputDirectory)" -Verbose
foreach ($bundle in $signedBundles) {
Copy-Item -Path $bundle.FullName -Destination "$(ob_outputDirectory)" -Verbose
}
Write-Verbose -Verbose "Uploaded Bundle:"
Write-Verbose -Verbose "Uploaded Bundles:"
Get-ChildItem -Path $(ob_outputDirectory) | Write-Verbose -Verbose
displayName: Upload msixbundle to Artifacts
- pwsh: |
Write-Verbose -Verbose "Pipeline.Workspace: $(Pipeline.Workspace)"
Get-ChildItem -Path $(Pipeline.Workspace) -Recurse | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "System.DefaultWorkingDirectory: $(System.DefaultWorkingDirectory)"
Get-ChildItem -Path $(System.DefaultWorkingDirectory) -Recurse | Select-Object -ExpandProperty FullName
Test-Path -Path '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP-Private.xml' | Write-Verbose -Verbose
displayName: Output Pipeline.Workspace and System.DefaultWorkingDirectory
- template: channelSelection.yml@self
- pwsh: |
$IsLTS = '$(ChannelSelection.IsLTS)' -eq 'true'
$IsStable = '$(ChannelSelection.IsStable)' -eq 'true'
$IsPreview = '$(ChannelSelection.IsPreview)' -eq 'true'
Write-Verbose -Verbose "Channel Selection - LTS: $IsLTS, Stable: $IsStable, Preview: $IsPreview"
# Define app configurations for each channel
$channelConfigs = @{
'LTS' = @{
AppStoreName = 'PowerShell-LTS'
ProductId = '$(productId-LTS)'
AppId = '$(AppID-LTS)'
ServiceEndpoint = "StoreAppPublish-Stable"
}
'Stable' = @{
AppStoreName = 'PowerShell'
ProductId = '$(productId-Stable)'
AppId = '$(AppID-Stable)'
ServiceEndpoint = "StoreAppPublish-Stable"
}
'Preview' = @{
AppStoreName = 'PowerShell (Preview)'
ProductId = '$(productId-Preview)'
AppId = '$(AppID-Preview)'
ServiceEndpoint = "StoreAppPublish-Preview"
}
}
$currentChannel = if ($IsLTS) { 'LTS' }
elseif ($IsStable) { 'Stable' }
elseif ($IsPreview) { 'Preview' }
else {
Write-Error "No valid channel detected"
exit 1
}
$config = $channelConfigs[$currentChannel]
Write-Verbose -Verbose "Selected channel: $currentChannel"
Write-Verbose -Verbose "App Store Name: $($config.AppStoreName)"
Write-Verbose -Verbose "Product ID: $($config.ProductId)"
# Update PDP.xml file
$pdpPath = '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP/en-US/PDP.xml'
if (Test-Path $pdpPath) {
Write-Verbose -Verbose "Updating PDP file: $pdpPath"
[xml]$pdpXml = Get-Content $pdpPath -Raw
# Create namespace manager for XML with default namespace
$nsManager = New-Object System.Xml.XmlNamespaceManager($pdpXml.NameTable)
$nsManager.AddNamespace("pd", "http://schemas.microsoft.com/appx/2012/ProductDescription")
$appStoreNameElement = $pdpXml.SelectSingleNode("//pd:AppStoreName", $nsManager)
if ($appStoreNameElement) {
$appStoreNameElement.SetAttribute("_locID", $config.AppStoreName)
Write-Verbose -Verbose "Updated AppStoreName _locID to: $($config.AppStoreName)"
} else {
Write-Warning "AppStoreName element not found in PDP file"
}
$pdpXml.Save($pdpPath)
Write-Verbose -Verbose "PDP file updated successfully"
Get-Content -Path $pdpPath | Write-Verbose -Verbose
} else {
Write-Error "PDP file not found: $pdpPath"
exit 1
}
# Update SBConfig.json file
$sbConfigPath = '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/SBConfig.json'
if (Test-Path $sbConfigPath) {
Write-Verbose -Verbose "Updating SBConfig file: $sbConfigPath"
$sbConfigJson = Get-Content $sbConfigPath -Raw | ConvertFrom-Json
$sbConfigJson.appSubmission.productId = $config.ProductId
Write-Verbose -Verbose "Updated productId to: $($config.ProductId)"
$sbConfigJson | ConvertTo-Json -Depth 100 | Set-Content $sbConfigPath -Encoding UTF8
Write-Verbose -Verbose "SBConfig file updated successfully"
Get-Content -Path $sbConfigPath | Write-Verbose -Verbose
} else {
Write-Error "SBConfig file not found: $sbConfigPath"
exit 1
}
Write-Host "##vso[task.setvariable variable=ServiceConnection]$($config.ServiceEndpoint)"
Write-Host "##vso[task.setvariable variable=SBConfigPath]$($sbConfigPath)"
# These variables are used in the next tasks to determine which ServiceEndpoint to use
$ltsValue = $IsLTS.ToString().ToLower()
$stableValue = $IsStable.ToString().ToLower()
$previewValue = $IsPreview.ToString().ToLower()
Write-Verbose -Verbose "About to set variables:"
Write-Verbose -Verbose " LTS=$ltsValue"
Write-Verbose -Verbose " STABLE=$stableValue"
Write-Verbose -Verbose " PREVIEW=$previewValue"
Write-Host "##vso[task.setvariable variable=LTS]$ltsValue"
Write-Host "##vso[task.setvariable variable=STABLE]$stableValue"
Write-Host "##vso[task.setvariable variable=PREVIEW]$previewValue"
Write-Verbose -Verbose "Variables set successfully"
name: UpdateConfigs
displayName: Update PDPs and SBConfig.json
- pwsh: |
Write-Verbose -Verbose "Checking variables after UpdateConfigs:"
Write-Verbose -Verbose "LTS=$(LTS)"
Write-Verbose -Verbose "STABLE=$(STABLE)"
Write-Verbose -Verbose "PREVIEW=$(PREVIEW)"
displayName: Debug - Check Variables
- task: MS-RDX-MRO.windows-store-publish.package-task.store-package@3
displayName: 'Create StoreBroker Package (Preview)'
condition: eq(variables['PREVIEW'], 'true')
inputs:
serviceEndpoint: 'StoreAppPublish-Preview'
sbConfigPath: '$(SBConfigPath)'
sourceFolder: '$(BundleDir)'
contents: '*.msixBundle'
outSBName: 'PowerShellStorePackage'
pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP'
pdpMediaPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP-Media'
- task: MS-RDX-MRO.windows-store-publish.package-task.store-package@3
displayName: 'Create StoreBroker Package (Stable/LTS)'
condition: or(eq(variables['STABLE'], 'true'), eq(variables['LTS'], 'true'))
inputs:
serviceEndpoint: 'StoreAppPublish-Stable'
sbConfigPath: '$(SBConfigPath)'
sourceFolder: '$(BundleDir)'
contents: '*.msixBundle'
outSBName: 'PowerShellStorePackage'
pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP'
pdpMediaPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDP/PDP-Media'
- pwsh: |
Get-Item -Path "$(System.DefaultWorkingDirectory)/SBLog.txt" -ErrorAction SilentlyContinue |
Copy-Item -Destination "$(ob_outputDirectory)" -Verbose
displayName: Upload Store Failure Log
condition: failed()
- pwsh: |
$submissionPackageDir = "$(System.DefaultWorkingDirectory)/SBOutDir"
$jsonFile = "$submissionPackageDir/PowerShellStorePackage.json"
$zipFile = "$submissionPackageDir/PowerShellStorePackage.zip"
if ((Test-Path $jsonFile) -and (Test-Path $zipFile)) {
Write-Verbose -Verbose "Uploading StoreBroker Package files:"
Write-Verbose -Verbose "JSON File: $jsonFile"
Write-Verbose -Verbose "ZIP File: $zipFile"
Copy-Item -Path $submissionPackageDir -Destination "$(ob_outputDirectory)" -Verbose -Recurse
}
else {
Write-Error "Required files not found in $submissionPackageDir"
}
displayName: 'Upload StoreBroker Package'
@@ -0,0 +1,230 @@
jobs:
- job: CreateStorePackage
displayName: Create StoreBroker Package
pool:
type: windows
variables:
- group: 'Azure Blob variable group'
- group: 'Store Publish Variables'
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_signing_setup_enabled
value: false
- name: ob_sdl_codeSignValidation_enabled
value: false
steps:
- checkout: self
clean: true
- template: release-SetReleaseTagandContainerName.yml@self
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifact: drop_msixbundle_CreateMSIXBundle
itemPattern: |
**/*.msixbundle
targetPath: '$(Build.ArtifactStagingDirectory)/downloads'
displayName: Download signed msixbundle
- pwsh: |
$bundleDir = '$(Build.ArtifactStagingDirectory)/downloads'
$bundle = Get-ChildItem -Path $bundleDir -Filter '*.msixbundle' -Recurse | Select-Object -First 1
if (-not $bundle) {
Write-Error "No .msixbundle file found in $bundleDir"
exit 1
}
Write-Verbose -Verbose "Found bundle: $($bundle.FullName)"
$vstsCommandString = "vso[task.setvariable variable=BundleDir]$($bundle.DirectoryName)"
Write-Host "##$vstsCommandString"
displayName: Locate msixbundle
- template: channelSelection.yml@self
- pwsh: |
$IsLTS = '$(ChannelSelection.IsLTS)' -eq 'true'
$IsStable = '$(ChannelSelection.IsStable)' -eq 'true'
$IsPreview = '$(ChannelSelection.IsPreview)' -eq 'true'
Write-Verbose -Verbose "Channel Selection - LTS: $IsLTS, Stable: $IsStable, Preview: $IsPreview"
# Define app configurations for each channel
$channelConfigs = @{
'LTS' = @{
ProductId = '$(productId-LTS)'
AppId = '$(AppID-LTS)'
ServiceEndpoint = "StoreAppPublish-Stable"
}
'Stable' = @{
ProductId = '$(productId-Stable)'
AppId = '$(AppID-Stable)'
ServiceEndpoint = "StoreAppPublish-Stable"
}
'Preview' = @{
ProductId = '$(productId-Preview)'
AppId = '$(AppID-Preview)'
ServiceEndpoint = "StoreAppPublish-Preview"
}
}
$currentChannel = if ($IsLTS) { 'LTS' }
elseif ($IsStable) { 'Stable' }
elseif ($IsPreview) { 'Preview' }
else { $null }
if (-not $currentChannel) {
Write-Host "##[warning]No release channel selected (LTS/Stable/Preview all false). Skipping Store package creation."
Write-Host "##vso[task.setvariable variable=SkipStorePublish]true"
# Set channel flags so any downstream conditioned tasks evaluate to skip.
Write-Host "##vso[task.setvariable variable=LTS]false"
Write-Host "##vso[task.setvariable variable=STABLE]false"
Write-Host "##vso[task.setvariable variable=PREVIEW]false"
# Ensure the output directory exists so downstream artifact publishing does not fail.
$outputDirectory = "$(ob_outputDirectory)"
if (-not (Test-Path -LiteralPath $outputDirectory)) {
New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null
}
return
}
Write-Host "##vso[task.setvariable variable=SkipStorePublish]false"
$config = $channelConfigs[$currentChannel]
Write-Verbose -Verbose "Selected channel: $currentChannel"
Write-Verbose -Verbose "Product ID: $($config.ProductId)"
# Update SBConfig.json file
$sbConfigPath = '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/SBConfig.json'
if (Test-Path $sbConfigPath) {
Write-Verbose -Verbose "Updating SBConfig file: $sbConfigPath"
$sbConfigJson = Get-Content $sbConfigPath -Raw | ConvertFrom-Json
$sbConfigJson.appSubmission.productId = $config.ProductId
Write-Verbose -Verbose "Updated productId to: $($config.ProductId)"
$sbConfigJson | ConvertTo-Json -Depth 100 | Set-Content $sbConfigPath -Encoding UTF8
Write-Verbose -Verbose "SBConfig file updated successfully"
Get-Content -Path $sbConfigPath | Write-Verbose -Verbose
} else {
Write-Error "SBConfig file not found: $sbConfigPath"
exit 1
}
Write-Host "##vso[task.setvariable variable=ServiceConnection]$($config.ServiceEndpoint)"
Write-Host "##vso[task.setvariable variable=SBConfigPath]$($sbConfigPath)"
# Select the correct bundle based on channel
$bundleFiles = @(Get-ChildItem -Path '$(BundleDir)' -Filter '*.msixbundle')
Write-Verbose -Verbose "Available bundles: $($bundleFiles.Name -join ', ')"
if ($IsLTS) {
$bundleFile = $bundleFiles | Where-Object { $_.Name -match '-LTS-' }
} else {
# Catches Stable or Preview
$bundleFile = $bundleFiles | Where-Object { $_.Name -notmatch '-LTS-' }
}
if (-not $bundleFile) {
Write-Error "No matching bundle found for channel '$currentChannel'. Available bundles: $($bundleFiles.Name -join ', ')"
exit 1
}
# Copy the selected bundle to a dedicated directory for store packaging
$storeBundleDir = '$(Pipeline.Workspace)\releasePipeline\msix\store-bundle'
New-Item $storeBundleDir -Type Directory -Force > $null
Copy-Item -Path $bundleFile.FullName -Destination $storeBundleDir -Force -Verbose
Write-Host "##vso[task.setvariable variable=StoreBundleDir]$storeBundleDir"
Write-Verbose -Verbose "Selected bundle for store packaging: $($bundleFile.Name)"
# These variables are used in the next tasks to determine which ServiceEndpoint to use
$ltsValue = $IsLTS.ToString().ToLower()
$stableValue = $IsStable.ToString().ToLower()
$previewValue = $IsPreview.ToString().ToLower()
Write-Verbose -Verbose "About to set variables:"
Write-Verbose -Verbose " LTS=$ltsValue"
Write-Verbose -Verbose " STABLE=$stableValue"
Write-Verbose -Verbose " PREVIEW=$previewValue"
Write-Host "##vso[task.setvariable variable=LTS]$ltsValue"
Write-Host "##vso[task.setvariable variable=STABLE]$stableValue"
Write-Host "##vso[task.setvariable variable=PREVIEW]$previewValue"
Write-Verbose -Verbose "Variables set successfully"
name: UpdateConfigs
displayName: Update SBConfig.json and Store Variables
- pwsh: |
Write-Verbose -Verbose "Checking variables after UpdateConfigs:"
Write-Verbose -Verbose "LTS=$(LTS)"
Write-Verbose -Verbose "STABLE=$(STABLE)"
Write-Verbose -Verbose "PREVIEW=$(PREVIEW)"
displayName: Debug - Check Variables
- task: MS-RDX-MRO.windows-store-publish.package-task.store-package@3
displayName: 'Create StoreBroker Package (Preview)'
condition: eq(variables['PREVIEW'], 'true')
inputs:
serviceEndpoint: 'StoreAppPublish-Preview'
sbConfigPath: '$(SBConfigPath)'
sourceFolder: '$(StoreBundleDir)'
contents: '*.msixBundle'
outSBName: 'PowerShellStorePackage'
pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDPs/PDP'
# StoreBroker v3 requires a media root with a PDP root, even when the PDP has no media.
pdpMediaPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDPs/PDP'
- task: MS-RDX-MRO.windows-store-publish.package-task.store-package@3
displayName: 'Create StoreBroker Package (Stable/LTS)'
condition: or(eq(variables['STABLE'], 'true'), eq(variables['LTS'], 'true'))
inputs:
serviceEndpoint: 'StoreAppPublish-Stable'
sbConfigPath: '$(SBConfigPath)'
sourceFolder: '$(StoreBundleDir)'
contents: '*.msixBundle'
outSBName: 'PowerShellStorePackage'
pdpPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDPs/PDP'
# StoreBroker v3 requires a media root with a PDP root, even when the PDP has no media.
pdpMediaPath: '$(System.DefaultWorkingDirectory)/PowerShell/.pipelines/store/PDPs/PDP'
- pwsh: |
$outputDirectory = "$(ob_outputDirectory)"
if (-not (Test-Path -LiteralPath $outputDirectory)) {
New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null
}
Get-Item -Path "$(System.DefaultWorkingDirectory)/SBLog.txt" -ErrorAction SilentlyContinue |
Copy-Item -Destination $outputDirectory -Verbose
displayName: Upload Store Failure Log
condition: failed()
- pwsh: |
$outputDirectory = "$(ob_outputDirectory)"
if (-not (Test-Path -LiteralPath $outputDirectory)) {
New-Item -ItemType Directory -Path $outputDirectory -Force | Out-Null
}
$submissionPackageDir = "$(System.DefaultWorkingDirectory)/SBOutDir"
$jsonFile = "$submissionPackageDir/PowerShellStorePackage.json"
$zipFile = "$submissionPackageDir/PowerShellStorePackage.zip"
if ((Test-Path $jsonFile) -and (Test-Path $zipFile)) {
Write-Verbose -Verbose "Uploading StoreBroker Package files:"
Write-Verbose -Verbose "JSON File: $jsonFile"
Write-Verbose -Verbose "ZIP File: $zipFile"
Copy-Item -Path $submissionPackageDir -Destination $outputDirectory -Verbose -Recurse
}
else {
Write-Error "Required files not found in $submissionPackageDir"
exit 1
}
displayName: 'Upload StoreBroker Package'
condition: and(succeeded(), ne(variables['SkipStorePublish'], 'true'))
@@ -1,5 +1,6 @@
parameters:
runtime: x64
dotnetArch: 'win-x64'
jobs:
- job: build_win_${{ parameters.runtime }}
@@ -63,16 +64,16 @@ jobs:
- download: CoOrdinatedBuildPipeline
artifact: drop_windows_build_windows_${{ parameters.runtime }}_release
displayName: Download signed artifacts
condition: ${{ ne(parameters.runtime, 'minSize') }}
condition: ${{ not(contains(parameters.runtime, 'minsize')) }}
- download: CoOrdinatedBuildPipeline
artifact: drop_windows_build_windows_x64_${{ parameters.runtime }}
artifact: drop_windows_build_windows_${{ parameters.runtime }}
displayName: Download minsize signed artifacts
condition: ${{ eq(parameters.runtime, 'minSize') }}
condition: ${{ contains(parameters.runtime, 'minsize') }}
- pwsh: |
Write-Verbose -Verbose "signed artifacts"
Get-ChildItem "$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_${{ parameters.runtime }}_release" -Recurse
Get-ChildItem "$(Pipeline.Workspace)\CoOrdinatedBuildPipeline" -Recurse
displayName: 'Capture Downloaded Artifacts'
# Diagnostics is not critical it passes every time it runs
continueOnError: true
@@ -80,6 +81,7 @@ jobs:
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
ob_restore_phase: false
architecture: ${{ parameters.dotnetArch }}
- pwsh: |
$runtime = '$(Runtime)'
@@ -91,7 +93,8 @@ jobs:
'arm64' { 'Signed-win-arm64' }
'fxdependent' { 'Signed-fxdependent' }
'fxdependentWinDesktop' { 'Signed-fxdependent-win-desktop' }
'minsize' { 'Signed-win7-x64' }
'x64_minsize' { 'Signed-win7-x64' }
'arm64_minsize' { 'Signed-win-arm64' }
}
Write-Verbose -Message "Init..." -Verbose
@@ -104,9 +107,9 @@ jobs:
Find-Dotnet
$signedFilesPath, $psoptionsFilePath = if ($env:RUNTIME -eq 'minsize') {
"$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_x64_${runtime}\$signedFolder"
"$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_x64_${runtime}\psoptions\psoptions.json"
$signedFilesPath, $psoptionsFilePath = if ($runtime.Contains('minsize')) {
"$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_${runtime}\$signedFolder"
"$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_${runtime}\psoptions\psoptions.json"
}
else {
"$(Pipeline.Workspace)\CoOrdinatedBuildPipeline\drop_windows_build_windows_${runtime}_release\$signedFolder"
@@ -136,12 +139,14 @@ jobs:
# Don't build LTS packages for rebuild branches
$LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch
$Stable = [bool]$metadata.StableRelease.Package
if ($isRebuildBranch) {
Write-Verbose -Message "Rebuild branch detected, skipping LTS package build" -Verbose
}
Write-Verbose -Verbose "LTS: $LTS"
Write-Verbose -Verbose "Stable: $Stable"
if ($LTS) {
Write-Verbose -Message "LTS Release: $LTS"
@@ -155,16 +160,18 @@ jobs:
'arm64' { 'win-arm64' }
'fxdependent' { 'win7-x64' }
'fxdependentWinDesktop' { 'win7-x64' }
'minsize' { 'win7-x64' }
'x64_minsize' { 'win7-x64' }
'arm64_minsize' { 'win-arm64' }
}
$packageTypes = switch ($runtime) {
'x64' { @('msi', 'zip', 'msix') }
'x86' { @('msi', 'zip', 'msix') }
'arm64' { @('msi', 'zip', 'msix') }
'x64' { @('zip', 'msix') }
'x86' { @('zip', 'msix') }
'arm64' { @('zip', 'msix') }
'fxdependent' { 'fxdependent' }
'fxdependentWinDesktop' { 'fxdependent-win-desktop' }
'minsize' { 'min-size' }
'x64_minsize' { 'min-size-x64' }
'arm64_minsize' { 'min-size-arm64' }
}
if (-not (Test-Path $(ob_outputDirectory))) {
@@ -175,6 +182,12 @@ jobs:
Start-PSPackage -Type $packageTypes -SkipReleaseChecks -WindowsRuntime $WindowsRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath -LTS:$LTS
# When both LTS and Stable are requested, also build the Stable MSIX
if ($packageTypes -contains 'msix' -and $LTS -and $Stable) {
Write-Verbose -Verbose "Both LTS and Stable packages requested. Building additional Stable MSIX."
Start-PSPackage -Type msix -SkipReleaseChecks -WindowsRuntime $WindowsRuntime -ReleaseTag $(ReleaseTagVar) -PackageBinPath $signedFilesPath
}
displayName: 'Build Packages (Unsigned)'
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
@@ -185,26 +198,20 @@ jobs:
Write-Verbose -Verbose "runtime = '$(Runtime)'"
$packageTypes = switch ($runtime) {
'x64' { @('msi', 'zip', 'msix') }
'x86' { @('msi', 'zip', 'msix') }
'arm64' { @('msi', 'zip', 'msix') }
'x64' { @('zip', 'msix') }
'x86' { @('zip', 'msix') }
'arm64' { @('zip', 'msix') }
'fxdependent' { 'fxdependent' }
'fxdependentWinDesktop' { 'fxdependent-win-desktop' }
'minsize' { 'min-size' }
'x64_minsize' { 'min-size-x64' }
'arm64_minsize' { 'min-size-arm64' }
}
if (-not (Test-Path $(ob_outputDirectory))) {
New-Item -ItemType Directory -Path $(ob_outputDirectory) -Force
}
if ($packageTypes -contains 'msi') {
$msiPkgNameFilter = "powershell-*.msi"
$msiPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $msiPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "unsigned msiPkgPath: $msiPkgPath"
Copy-Item -Path $msiPkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
}
if ($packageTypes -contains 'zip' -or $packageTypes -contains 'fxdependent' -or $packageTypes -contains 'min-size' -or $packageTypes -contains 'fxdependent-win-desktop') {
if ($packageTypes -contains 'zip' -or $packageTypes -like 'fxdependent*' -or $packageTypes -like 'min-size*') {
$zipPkgNameFilter = "powershell-*.zip"
$zipPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $zipPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "unsigned zipPkgPath: $zipPkgPath"
@@ -212,7 +219,7 @@ jobs:
}
if ($packageTypes -contains 'msix') {
$msixPkgNameFilter = "powershell-*.msix"
$msixPkgNameFilter = "PowerShell*.msix"
$msixPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $msixPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "unsigned msixPkgPath: $msixPkgPath"
Copy-Item -Path $msixPkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
+9 -107
View File
@@ -67,134 +67,36 @@ jobs:
- template: /.pipelines/templates/install-dotnet.yml@self
# Import build.psm1 and bootstrap packaging dependencies (WiX Toolset)
# Import build.psm1 and bootstrap packaging dependencies
- pwsh: |
$repoRoot = "$env:REPOROOT"
Import-Module "$repoRoot\build.psm1"
Import-Module "$repoRoot\tools\packaging"
Write-Verbose -Verbose "Modules imported successfully"
# Install WiX Toolset for EXE package creation
$isArm64 = '$(Runtime)' -eq 'arm64'
$env:RUNTIME = '$(Runtime)'
Start-PSBootstrap -Scenario Package
displayName: 'Import modules and install WiX Toolset'
displayName: 'Import modules'
env:
ob_restore_phase: true
# Sign MSI packages
- task: onebranch.pipeline.signing@1
displayName: Sign MSI packages
inputs:
command: 'sign'
signing_profile: external_distribution
files_to_sign: '**\*.msi'
search_root: '$(Pipeline.Workspace)'
# Create EXE package from signed MSI (for x64, x86, arm64 only)
- pwsh: |
$runtime = '$(Runtime)'
Write-Verbose -Verbose "runtime = '$(Runtime)'"
$repoRoot = "$env:REPOROOT"
Import-Module "$repoRoot\build.psm1"
Import-Module "$repoRoot\tools\packaging"
$noExeRuntimes = @('fxdependent', 'fxdependentWinDesktop', 'minsize')
if ($runtime -in $noExeRuntimes) {
Write-Verbose -Verbose "No EXE generated for $runtime"
return
}
$version = '$(Version)'
$msiLocation = Get-ChildItem -Path $(Pipeline.Workspace) -Recurse -Filter "powershell-*$runtime.msi" | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "msiLocation: $msiLocation"
Set-Location $repoRoot
$exePath = New-ExePackage -ProductVersion $version -ProductTargetArchitecture $runtime -MsiLocationPath $msiLocation
Write-Verbose -Verbose "setting vso[task.setvariable variable=exePath]$exePath"
Write-Host "##vso[task.setvariable variable=exePath]$exePath"
Write-Verbose -Verbose "exePath: $exePath"
$enginePath = Join-Path -Path '$(System.ArtifactsDirectory)\unsignedEngine' -ChildPath engine.exe
Expand-ExePackageEngine -ExePath $exePath -EnginePath $enginePath -ProductTargetArchitecture $runtime
displayName: 'Make exe and expand package'
# Sign EXE engine
- task: onebranch.pipeline.signing@1
displayName: Sign exe engine
inputs:
command: 'sign'
signing_profile: $(msft_3rd_party_cert_id)
files_to_sign: '$(System.ArtifactsDirectory)\unsignedEngine\*.exe'
search_root: '$(Pipeline.Workspace)'
# Compress signed EXE engine back into package
- pwsh: |
$runtime = '$(Runtime)'
Write-Verbose -Verbose "runtime = '$(Runtime)'"
$repoRoot = "$env:REPOROOT"
Import-Module "$repoRoot\build.psm1"
Import-Module "$repoRoot\tools\packaging"
$noExeRuntimes = @('fxdependent', 'fxdependentWinDesktop', 'minsize')
if ($runtime -in $noExeRuntimes) {
Write-Verbose -Verbose "No EXE generated for $runtime"
return
}
$exePath = '$(exePath)'
$enginePath = Join-Path -Path '$(System.ArtifactsDirectory)\unsignedEngine' -ChildPath engine.exe
$enginePath | Get-AuthenticodeSignature | out-string | Write-Verbose -verbose
Compress-ExePackageEngine -ExePath $exePath -EnginePath $enginePath -ProductTargetArchitecture $runtime
displayName: Compress signed exe package
# Sign final EXE packages
- task: onebranch.pipeline.signing@1
displayName: Sign exe packages
inputs:
command: 'sign'
signing_profile: external_distribution
files_to_sign: '**\*.exe'
search_root: '$(Pipeline.Workspace)'
# Copy all signed packages to output directory
- pwsh: |
$runtime = '$(Runtime)'
Write-Verbose -Verbose "runtime = '$(Runtime)'"
$packageTypes = switch ($runtime) {
'x64' { @('msi', 'zip', 'msix', 'exe') }
'x86' { @('msi', 'zip', 'msix', 'exe') }
'arm64' { @('msi', 'zip', 'msix', 'exe') }
'x64' { @('zip', 'msix') }
'x86' { @('zip', 'msix') }
'arm64' { @('zip', 'msix') }
'fxdependent' { 'fxdependent' }
'fxdependentWinDesktop' { 'fxdependent-win-desktop' }
'minsize' { 'min-size' }
'x64_minsize' { 'min-size-x64' }
'arm64_minsize' { 'min-size-arm64' }
}
if (-not (Test-Path $(ob_outputDirectory))) {
New-Item -ItemType Directory -Path $(ob_outputDirectory) -Force
}
if ($packageTypes -contains 'msi') {
$msiPkgNameFilter = "powershell-*.msi"
$msiPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $msiPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "signed msiPkgPath: $msiPkgPath"
Copy-Item -Path $msiPkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
}
if ($packageTypes -contains 'exe') {
$exePkgNameFilter = "powershell-*.exe"
$exePkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $exePkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "signed exePkgPath: $exePkgPath"
Copy-Item -Path $exePkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
}
if ($packageTypes -contains 'zip' -or $packageTypes -contains 'fxdependent' -or $packageTypes -contains 'min-size' -or $packageTypes -contains 'fxdependent-win-desktop') {
if ($packageTypes -contains 'zip' -or $packageTypes -like 'fxdependent*' -or $packageTypes -like 'min-size*') {
$zipPkgNameFilter = "powershell-*.zip"
$zipPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $zipPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "signed zipPkgPath: $zipPkgPath"
@@ -202,7 +104,7 @@ jobs:
}
if ($packageTypes -contains 'msix') {
$msixPkgNameFilter = "powershell-*.msix"
$msixPkgNameFilter = "PowerShell*.msix"
$msixPkgPath = Get-ChildItem -Path $(Pipeline.Workspace) -Filter $msixPkgNameFilter -Recurse -File | Select-Object -ExpandProperty FullName
Write-Verbose -Verbose "signed msixPkgPath: $msixPkgPath"
Copy-Item -Path $msixPkgPath -Destination '$(ob_outputDirectory)' -Force -Verbose
+49 -13
View File
@@ -12,7 +12,7 @@ jobs:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_msixbundle_CreateMSIXBundle
artifactName: drop_store_package_CreateStorePackage
variables:
- group: 'Store Publish Variables'
- name: LTS
@@ -21,7 +21,7 @@ jobs:
value: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['ChannelSelection.IsStable'] ]
- name: PREVIEW
value: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['ChannelSelection.IsPreview'] ]
- template: ./variable/release-shared.yml@self
- template: ./variables/release-shared.yml@self
parameters:
RELEASETAG: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['OutputReleaseTag.releaseTag'] ]
steps:
@@ -34,6 +34,7 @@ jobs:
displayName: 'Capture ReleaseTag and Downloaded Packages'
- task: PowerShell@2
condition: or(eq(variables['LTS'], 'true'), eq(variables['STABLE'], 'true'), eq(variables['PREVIEW'], 'true'))
inputs:
targetType: inline
script: |
@@ -51,24 +52,51 @@ jobs:
}
$endURL = $tagString -replace '^v','' -replace '\.',''
$message = "Changelog: https://github.com/PowerShell/PowerShell/blob/master/CHANGELOG/$middleURL.md#$endURL"
$changelogLink = "https://github.com/PowerShell/PowerShell/blob/master/CHANGELOG/$middleURL.md#$endURL"
Write-Verbose -Verbose "Release Notes for the Store:"
Write-Verbose -Verbose "$message"
$jsonPath = "$(Pipeline.Workspace)\SBOutDir\PowerShellStorePackage.json"
$json = Get-Content $jsonPath -Raw | ConvertFrom-Json
$json.listings.'en-us'.baseListing.releaseNotes = $message
$releaseNoteVariables = @{
'___VERSION___' = $tagString
'___CHANGELOGLINK___' = $changelogLink
}
$listingProperties = @($json.listings.PSObject.Properties)
if ($listingProperties.Count -eq 0) {
throw "Store listings are missing from '$jsonPath'."
}
foreach ($listingProperty in $listingProperties) {
$language = $listingProperty.Name
$releaseNotes = $listingProperty.Value.baseListing.releaseNotes
if ([string]::IsNullOrWhiteSpace($releaseNotes)) {
throw "Store release notes for '$language' are missing from '$jsonPath'."
}
foreach ($placeholder in $releaseNoteVariables.Keys) {
if (-not $releaseNotes.Contains($placeholder)) {
throw "Store release notes for '$language' do not contain the required placeholder '$placeholder'."
}
$releaseNotes = $releaseNotes.Replace($placeholder, $releaseNoteVariables[$placeholder])
}
$listingProperty.Value.baseListing.releaseNotes = $releaseNotes
Write-Verbose -Verbose "Release notes for '$language':"
Write-Verbose -Verbose $releaseNotes
}
$json | ConvertTo-Json -Depth 100 | Set-Content $jsonPath -Encoding UTF8
displayName: 'Update Release Notes in JSON'
displayName: 'Set Store Release Note Variables'
- task: PowerShell@2
condition: or(eq(variables['LTS'], 'true'), eq(variables['STABLE'], 'true'), eq(variables['PREVIEW'], 'true'))
inputs:
targetType: inline
script: |
# Convert ADO variables to PowerShell boolean variables
$IsLTS = '$(LTS)' -eq 'true'
$IsStable = '$(STABLE)' -eq 'true'
$IsStable = '$(STABLE)' -eq 'true'
$IsPreview = '$(PREVIEW)' -eq 'true'
Write-Verbose -Verbose "Channel Selection - LTS: $(LTS), Stable: $(STABLE), Preview: $(PREVIEW)"
@@ -76,10 +104,12 @@ jobs:
$currentChannel = if ($IsLTS) { 'LTS' }
elseif ($IsStable) { 'Stable' }
elseif ($IsPreview) { 'Preview' }
else {
Write-Error "No valid channel detected"
exit 1
}
else { $null }
if (-not $currentChannel) {
Write-Host "##[warning]No release channel selected (LTS/Stable/Preview all false). Skipping Store publish."
return
}
# Assign AppID for Store-Publish Task
$appID = $null
@@ -100,26 +130,32 @@ jobs:
- task: MS-RDX-MRO.windows-store-publish.publish-task.store-publish@3
displayName: 'Publish StoreBroker Package (Stable/LTS)'
condition: and(ne('${{ parameters.skipMSIXPublish }}', 'true'), or(eq(variables['STABLE'], 'true'), eq(variables['LTS'], 'true')))
condition: and(not(${{ parameters.skipMSIXPublish }}), or(eq(variables['STABLE'], 'true'), eq(variables['LTS'], 'true')))
inputs:
serviceEndpoint: 'StoreAppPublish-Stable'
appId: '$(AppID)'
inputMethod: JsonAndZip
jsonPath: '$(Pipeline.Workspace)\SBOutDir\PowerShellStorePackage.json'
zipPath: '$(Pipeline.Workspace)\SBOutDir\PowerShellStorePackage.zip'
force: true
deletePackages: true
numberOfPackagesToKeep: 2
jsonZipUpdateMetadata: true
targetPublishMode: 'Immediate'
skipPolling: true
- task: MS-RDX-MRO.windows-store-publish.publish-task.store-publish@3
displayName: 'Publish StoreBroker Package (Preview)'
condition: and(ne('${{ parameters.skipMSIXPublish }}', 'true'), eq(variables['PREVIEW'], 'true'))
condition: and(not(${{ parameters.skipMSIXPublish }}), eq(variables['PREVIEW'], 'true'))
inputs:
serviceEndpoint: 'StoreAppPublish-Preview'
appId: '$(AppID)'
inputMethod: JsonAndZip
jsonPath: '$(Pipeline.Workspace)\SBOutDir\PowerShellStorePackage.json'
zipPath: '$(Pipeline.Workspace)\SBOutDir\PowerShellStorePackage.zip'
force: true
deletePackages: true
numberOfPackagesToKeep: 2
jsonZipUpdateMetadata: true
targetPublishMode: 'Immediate'
skipPolling: true
+59
View File
@@ -0,0 +1,59 @@
parameters:
- name: skipPublish
type: boolean
jobs:
- job: NuGetPublish
displayName: Publish to NuGet
condition: succeeded()
pool:
type: release
os: windows
templateContext:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_upload_upload_packages
variables:
- template: ./variables/release-shared.yml@self
parameters:
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['OutputVersion.Version'] ]
steps:
- task: PowerShell@2
inputs:
targetType: inline
script: |
Write-Verbose -Verbose "Version: $(Version)"
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: 'Capture Environment Variables'
- task: PowerShell@2
inputs:
targetType: inline
script: |
#Exclude all global tool packages. Their names start with 'PowerShell.'
$null = New-Item -ItemType Directory -Path "$(Pipeline.Workspace)/release"
Copy-Item "$(Pipeline.Workspace)/NuGetPackages/*.nupkg" -Destination "$(Pipeline.Workspace)/release" -Exclude "PowerShell.*.nupkg" -Force -Verbose
$releaseVersion = '$(Version)'
$globalToolPath = "$(Pipeline.Workspace)/NuGetPackages/PowerShell.$releaseVersion.nupkg"
if ($releaseVersion -notlike '*-*') {
# Copy the global tool package for stable releases
Copy-Item $globalToolPath -Destination "$(Pipeline.Workspace)/release"
}
Write-Verbose -Verbose "The .nupkgs below will be pushed:"
Get-ChildItem "$(Pipeline.Workspace)/release" -recurse
displayName: Download and capture nupkgs
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
inputs:
command: push
packagesToPush: '$(Pipeline.Workspace)/release/*.nupkg'
nuGetFeedType: external
publishFeedCredentials: PowerShellNuGetOrgPush
@@ -17,7 +17,7 @@ jobs:
pipeline: PSPackagesOfficial
artifactName: drop_upload_upload_packages
variables:
- template: ./variable/release-shared.yml@self
- template: ./variables/release-shared.yml@self
parameters:
RELEASETAG: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['OutputReleaseTag.releaseTag'] ]
@@ -35,6 +35,21 @@ jobs:
targetType: inline
script: |
$Path = "$(Pipeline.Workspace)/GitHubPackages"
# The .exe packages are for Windows Update only and should not be uploaded to GitHub release.
$exefiles = Get-ChildItem -Path $Path -Filter *.exe
if ($exefiles) {
Write-Verbose -Verbose "Remove .exe packages:"
$exefiles | Remove-Item -Force -Verbose
}
# The .msi packages should not be uploaded to GitHub release.
$msifiles = Get-ChildItem -Path $Path -Filter *.msi
if ($msifiles) {
Write-Verbose -Verbose "Remove .msi packages:"
$msifiles | Remove-Item -Force -Verbose
}
$OutputPath = Join-Path $Path 'hashes.sha256'
$packages = Get-ChildItem -Path $Path -Include * -Recurse -File
$checksums = $packages |
@@ -74,11 +89,21 @@ jobs:
$changelog = Get-Content -Path $filePath
$headingPattern = "^## \[\d+\.\d+\.\d+"
$headingStartLines = $changelog | Select-String -Pattern $headingPattern | Select-Object -ExpandProperty LineNumber
$headingStartLines = @($changelog | Select-String -Pattern $headingPattern | Select-Object -ExpandProperty LineNumber)
if ($headingStartLines.Count -eq 0) {
throw "No release heading matching '$headingPattern' found in $filePath"
}
$startLine = $headingStartLines[0]
$endLine = $headingStartLines[1] - 1
$clContent = $changelog | Select-Object -Skip ($startLine-1) -First ($endLine - $startLine) | Out-String
if ($headingStartLines.Count -ge 2) {
$endLine = $headingStartLines[1] - 1
} else {
# Only one release heading present; take through end of file.
$endLine = $changelog.Count
}
$clContent = $changelog | Select-Object -Skip ($startLine-1) -First ($endLine - $startLine + 1) | Out-String
$StringBuilder = [System.Text.StringBuilder]::new($clContent, $clContent.Length + 2kb)
$StringBuilder.AppendLine().AppendLine() > $null
@@ -146,58 +171,3 @@ jobs:
action: 'create'
releaseNotesFilePath: '$(ReleaseNotesFilePath)'
isPrerelease: '$(IsPreRelease)'
- job: NuGetPublish
displayName: Publish to NuGet
condition: succeeded()
pool:
type: release
os: windows
templateContext:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_upload_upload_packages
variables:
- template: ./variable/release-shared.yml@self
parameters:
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.SetTagAndChangelog.outputs['OutputVersion.Version'] ]
steps:
- task: PowerShell@2
inputs:
targetType: inline
script: |
Write-Verbose -Verbose "Version: $(Version)"
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: 'Capture Environment Variables'
- task: PowerShell@2
inputs:
targetType: inline
script: |
#Exclude all global tool packages. Their names start with 'PowerShell.'
$null = New-Item -ItemType Directory -Path "$(Pipeline.Workspace)/release"
Copy-Item "$(Pipeline.Workspace)/NuGetPackages/*.nupkg" -Destination "$(Pipeline.Workspace)/release" -Exclude "PowerShell.*.nupkg" -Force -Verbose
$releaseVersion = '$(Version)'
$globalToolPath = "$(Pipeline.Workspace)/NuGetPackages/PowerShell.$releaseVersion.nupkg"
if ($releaseVersion -notlike '*-*') {
# Copy the global tool package for stable releases
Copy-Item $globalToolPath -Destination "$(Pipeline.Workspace)/release"
}
Write-Verbose -Verbose "The .nupkgs below will be pushed:"
Get-ChildItem "$(Pipeline.Workspace)/release" -recurse
displayName: Download and capture nupkgs
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
inputs:
command: push
packagesToPush: '$(Pipeline.Workspace)/release/*.nupkg'
nuGetFeedType: external
publishFeedCredentials: PowerShellNuGetOrgPush
+24 -41
View File
@@ -11,6 +11,23 @@ stages:
displayName: 'Copy EV2 Files to Artifact'
pool:
type: linux
templateContext:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_linux_package_deb
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_linux_package_deb_arm64
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_linux_package_rpm
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_linux_package_mariner_x64
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_linux_package_mariner_arm64
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
@@ -23,7 +40,9 @@ stages:
- group: 'mscodehub-code-read-akv'
- group: 'packages.microsoft.com'
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
value: $(Build.SourcesDirectory)/PowerShell/.config/suppress.json
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)/PowerShell/.config/tsaoptions.json
steps:
- checkout: self ## the global setting on lfs didn't work
lfs: false
@@ -43,20 +62,6 @@ stages:
env:
ob_restore_phase: true
- pwsh: |
$branch = 'mirror-target'
$gitArgs = "clone",
"--verbose",
"--branch",
"$branch",
"https://$(mscodehubCodeReadPat)@mscodehub.visualstudio.com/PowerShellCore/_git/Internal-PowerShellTeam-Tools",
'$(Pipeline.Workspace)/tools'
$gitArgs | Write-Verbose -Verbose
git $gitArgs
displayName: Clone Internal-PowerShellTeam-Tools from MSCodeHub
env:
ob_restore_phase: true
- pwsh: |
Get-ChildItem Env: | Out-String -Stream | write-Verbose -Verbose
displayName: 'Capture Environment Variables'
@@ -99,39 +104,17 @@ stages:
env:
ob_restore_phase: true
- download: PSPackagesOfficial
artifact: 'drop_linux_package_deb'
displayName: 'Download artifact containing .deb_amd64.deb file from PSPackagesOfficial triggering pipeline'
env:
ob_restore_phase: true
- download: PSPackagesOfficial
artifact: 'drop_linux_package_rpm'
displayName: 'Download artifact containing .rh.x64_86.rpm file from PSPackagesOfficial triggering pipeline'
env:
ob_restore_phase: true
- download: PSPackagesOfficial
artifact: 'drop_linux_package_mariner_x64'
displayName: 'Download artifact containing .cm.x86_64.rpm file from PSPackagesOfficial triggering pipeline'
env:
ob_restore_phase: true
- download: PSPackagesOfficial
artifact: 'drop_linux_package_mariner_arm64'
displayName: 'Download artifact containing .cm.aarch64.rpm file from PSPackagesOfficial triggering pipeline'
env:
ob_restore_phase: true
- pwsh: |
Write-Verbose -Verbose "Copy ESRP signed .deb and .rpm packages"
$downloadedPipelineFolder = Join-Path '$(Pipeline.Workspace)' -ChildPath 'PSPackagesOfficial'
# templateContext.inputs places the PSPackagesOfficial pipelineArtifact files
# directly under $(Pipeline.Workspace), not in per-artifact subfolders.
$downloadedPipelineFolder = '$(Pipeline.Workspace)'
$srcFilesFolder = Join-Path -Path '$(Pipeline.Workspace)' -ChildPath 'SourceFiles'
New-Item -Path $srcFilesFolder -ItemType Directory
$packagesFolder = Join-Path -Path $srcFilesFolder -ChildPath 'packages'
New-Item -Path $packagesFolder -ItemType Directory
$packageFiles = Get-ChildItem -Path $downloadedPipelineFolder -Recurse -Directory -Filter "drop_*" | Get-ChildItem -File -Include *.deb, *.rpm
$packageFiles = Get-ChildItem -Path $downloadedPipelineFolder -File | Where-Object { $_.Extension -in '.deb', '.rpm' }
foreach ($file in $packageFiles)
{
Write-Verbose -Verbose "copying file: $($file.FullName)"
+42 -23
View File
@@ -1,37 +1,56 @@
parameters:
- name: releaseEnvironment
type: string
default: Production
values:
- Production
- PPE
- Test
- name: approvalServiceEnvironment
type: string
default: Production
values:
- Production
- PPE
- Test
# OneBranch requires the stage name to be prefixed with the release environment.
# Official uses 'Prod' for Production; NonProd validators require '<env>' (e.g. 'Test', 'PPE').
- name: stagePrefix
type: string
default: Prod
# When true, the Ev2 push step is skipped. Useful for NonOfficial dry-runs that
# only want to validate artifact download via templateContext.inputs.
- name: skipEv2Push
type: boolean
default: false
stages:
- stage: 'Prod_Release'
- stage: ${{ parameters.stagePrefix }}_Release
displayName: 'Deploy packages to PMC with EV2'
dependsOn:
- PrepForEV2
variables:
- name: ob_release_environment
value: "Production"
value: ${{ parameters.releaseEnvironment }}
- name: repoRoot
value: $(Build.SourcesDirectory)
jobs:
- job: Prod_ReleaseJob
- job: ${{ parameters.stagePrefix }}_ReleaseJob
displayName: Publish to PMC
pool:
type: release
templateContext:
inputs:
- input: pipelineArtifact
artifactName: drop_PrepForEV2_CopyEv2FilesToArtifact
steps:
- task: DownloadPipelineArtifact@2
inputs:
targetPath: '$(Pipeline.Workspace)'
artifact: drop_PrepForEV2_CopyEv2FilesToArtifact
displayName: 'Download drop_PrepForEV2_CopyEv2FilesToArtifact artifact that has all files needed'
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
targetPath: '$(Pipeline.Workspace)'
displayName: 'Download to get EV2 Files'
- task: vsrm-ev2.vss-services-ev2.adm-release-task.ExpressV2Internal@1
displayName: 'Ev2: Push to PMC'
inputs:
UseServerMonitorTask: true
EndpointProviderType: ApprovalService
ApprovalServiceEnvironment: Production
ServiceRootPath: '$(Pipeline.Workspace)/drop_PrepForEV2_CopyEV2FilesToArtifact/EV2Specs/ServiceGroupRoot'
RolloutSpecPath: '$(Pipeline.Workspace)/drop_PrepForEV2_CopyEV2FilesToArtifact/EV2Specs/ServiceGroupRoot/RolloutSpec.json'
- ${{ if not(parameters.skipEv2Push) }}:
- task: vsrm-ev2.vss-services-ev2.adm-release-task.ExpressV2Internal@1
displayName: 'Ev2: Push to PMC'
inputs:
UseServerMonitorTask: true
EndpointProviderType: ApprovalService
ApprovalServiceEnvironment: ${{ parameters.approvalServiceEnvironment }}
ServiceRootPath: '$(Pipeline.Workspace)/EV2Specs/ServiceGroupRoot'
RolloutSpecPath: '$(Pipeline.Workspace)/EV2Specs/ServiceGroupRoot/RolloutSpec.json'
@@ -51,14 +51,17 @@ jobs:
Import-Module "$toolsDirectory/ci.psm1"
$jsonFile = Get-Item "$ENV:PIPELINE_WORKSPACE/PSPackagesOfficial/BuildInfoJson/*.json"
$fileName = Split-Path $jsonFile -Leaf
# The build itself has already determined if it is preview or stable/LTS,
# we just need to check via the file name
$isPreview = $fileName -eq "preview.json"
$isStable = $fileName -eq "stable.json"
$dateTime = [datetime]::UtcNow
$dateTime = [datetime]::new($dateTime.Ticks - ($dateTime.Ticks % [timespan]::TicksPerSecond), $dateTime.Kind)
$metadata = Get-Content -LiteralPath "$toolsDirectory/metadata.json" -ErrorAction Stop | ConvertFrom-Json
$stableReleaseTag = $metadata.StableReleaseTag -Replace 'v',''
$currentReleaseTag = $buildInfo.ReleaseTag -Replace 'v',''
# Note: version tags in metadata.json (e.g. StableReleaseTag) may not reflect the current release being
# published, so they must not be used to gate channel decisions. Use the explicit publish flags instead.
$stableRelease = $metadata.StableRelease.PublishToChannels
$ltsRelease = $metadata.LTSRelease.PublishToChannels
@@ -73,7 +76,7 @@ jobs:
$targetFile = "$ENV:PIPELINE_WORKSPACE/$fileName"
ConvertTo-Json -InputObject $buildInfo | Out-File $targetFile -Encoding ascii
if ($fileName -eq "preview.json") {
if ($isPreview) {
Set-BuildVariable -Name UploadPreview -Value YES
} else {
Set-BuildVariable -Name UploadPreview -Value NO
@@ -82,9 +85,7 @@ jobs:
Set-BuildVariable -Name PreviewBuildInfoFile -Value $targetFile
## Create 'lts.json' if marked as a LTS release.
if ($fileName -eq "stable.json") {
[System.Management.Automation.SemanticVersion] $stableVersion = $stableReleaseTag
[System.Management.Automation.SemanticVersion] $currentVersion = $currentReleaseTag
if ($isStable) {
if ($ltsRelease) {
$ltsFile = "$ENV:PIPELINE_WORKSPACE/lts.json"
Copy-Item -Path $targetFile -Destination $ltsFile -Force
@@ -94,18 +95,24 @@ jobs:
Set-BuildVariable -Name UploadLTS -Value NO
}
## Only update the stable.json if the current version is greater than the stable version.
if ($currentVersion -gt $stableVersion) {
$versionFile = "$ENV:PIPELINE_WORKSPACE/$($currentVersion.Major)-$($currentVersion.Minor).json"
Copy-Item -Path $targetFile -Destination $versionFile -Force
Set-BuildVariable -Name StableBuildInfoFile -Value $versionFile
## Gate stable.json upload on the metadata publish flag.
if ($stableRelease) {
Set-BuildVariable -Name StableBuildInfoFile -Value $targetFile
Set-BuildVariable -Name UploadStable -Value YES
} else {
Set-BuildVariable -Name UploadStable -Value NO
}
## Always publish the version-specific {Major}-{Minor}.json for non-preview builds.
[System.Management.Automation.SemanticVersion] $currentVersion = $currentReleaseTag
$versionFile = "$ENV:PIPELINE_WORKSPACE/$($currentVersion.Major)-$($currentVersion.Minor).json"
Copy-Item -Path $targetFile -Destination $versionFile -Force
Set-BuildVariable -Name VersionSpecificBuildInfoFile -Value $versionFile
Set-BuildVariable -Name UploadVersionSpecific -Value YES
} else {
Set-BuildVariable -Name UploadStable -Value NO
Set-BuildVariable -Name UploadVersionSpecific -Value NO
}
displayName: Create json files
@@ -146,4 +153,12 @@ jobs:
Write-Verbose -Verbose "Uploading $jsonFile to $containerName/$prefix/$blobName"
Set-AzStorageBlobContent -File $jsonFile -Container $containerName -Blob "$prefix/$blobName" -Context $storageContext -Force
}
condition: and(succeeded(), or(eq(variables['UploadPreview'], 'YES'), eq(variables['UploadLTS'], 'YES'), eq(variables['UploadStable'], 'YES')))
#version-specific
if ($env:UploadVersionSpecific -eq 'YES') {
$jsonFile = "$env:VersionSpecificBuildInfoFile"
$blobName = Get-Item $jsonFile | Split-Path -Leaf
Write-Verbose -Verbose "Uploading $jsonFile to $containerName/$prefix/$blobName"
Set-AzStorageBlobContent -File $jsonFile -Container $containerName -Blob "$prefix/$blobName" -Context $storageContext -Force
}
condition: and(succeeded(), or(eq(variables['UploadPreview'], 'YES'), eq(variables['UploadLTS'], 'YES'), eq(variables['UploadStable'], 'YES'), eq(variables['UploadVersionSpecific'], 'YES')))
@@ -20,6 +20,20 @@ parameters:
- name: enableCredScan
type: boolean
default: true
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: dotnetArch
type: string
default: 'win-x64'
jobs:
- job: ${{ parameters.jobName }}
@@ -36,6 +50,8 @@ jobs:
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_sdl_credscan_enabled
value: ${{ parameters.enableCredScan }}
- name: ISEARLYACCESS
value: ${{ parameters.IsEarlyAccess }}
pool:
type: ${{ parameters.jobtype }}
@@ -46,6 +62,10 @@ jobs:
- checkout: self
clean: true
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
- template: release-SetReleaseTagandContainerName.yml@self
- download: PSPackagesOfficial
@@ -62,6 +82,10 @@ jobs:
displayName: 'Capture Downloaded Artifacts'
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
architecture: ${{ parameters.dotnetArch }}
${{ if eq(parameters.IsEarlyAccess, true) }}:
ob_restore_phase: false
- pwsh: |
$artifactName = '$(artifactName)'
@@ -1,10 +1,33 @@
parameters:
jobName: ""
displayName: ""
jobtype: "windows"
globalToolExeName: 'pwsh.exe'
globalToolPackageName: 'PowerShell.Windows.x64'
- name: jobName
type: string
default: ""
- name: displayName
type: string
default: ""
- name: jobtype
type: string
default: "windows"
- name: globalToolExeName
type: string
default: 'pwsh.exe'
- name: globalToolPackageName
type: string
default: 'PowerShell.Windows.x64'
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: dotnetArch
type: string
default: 'win-x64'
jobs:
- job: ${{ parameters.jobName }}
@@ -19,11 +42,17 @@ jobs:
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ISEARLYACCESS
value: ${{ parameters.IsEarlyAccess }}
steps:
- checkout: self
clean: true
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
- template: release-SetReleaseTagandContainerName.yml@self
- download: PSPackagesOfficial
@@ -39,6 +68,10 @@ jobs:
displayName: 'Capture Downloaded Artifacts'
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
architecture: ${{ parameters.dotnetArch }}
${{ if eq(parameters.IsEarlyAccess, true) }}:
ob_restore_phase: false
- pwsh: |
$repoRoot = "$(Build.SourcesDirectory)/PowerShell"
@@ -108,7 +108,7 @@ jobs:
}
if($message.count -gt 0){throw ($message | out-string)}
displayName: Validate Zip and MSI Package Names
displayName: Validate Zip Package Names
- pwsh: |
Import-Module ./tools/packaging/packaging.psm1 -Force
+61 -7
View File
@@ -1,8 +1,33 @@
parameters:
jobName: ""
displayName: ""
poolName: "windows"
imageName: 'none'
- name: jobName
type: string
default: ""
- name: displayName
type: string
default: ""
- name: poolName
type: string
default: "windows"
- name: imageName
type: string
default: 'none'
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: dotnetArch
type: string
default: 'win-x64'
- name: EarlyAccessFeed
type: string
default: 'net10'
jobs:
- job: ${{ parameters.jobName }}
@@ -22,15 +47,19 @@ jobs:
- group: mscodehub-feed-read-general
- group: mscodehub-feed-read-akv
- group: DotNetPrivateBuildAccess
- name: ISEARLYACCESS
value: ${{ parameters.IsEarlyAccess }}
- name: EARLY_ACCESS_FEED
value: ${{ parameters.EarlyAccessFeed }}
steps:
- checkout: self
clean: true
lfs: false
- template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
repoRoot: "$(Build.SourcesDirectory)"
ReleaseTagVar: $(ReleaseTagVar)
- template: release-SetReleaseTagandContainerName.yml@self
@@ -47,6 +76,11 @@ jobs:
displayName: 'Capture Downloaded Artifacts'
- template: /.pipelines/templates/install-dotnet.yml@self
parameters:
ob_restore_phase: false
architecture: ${{ parameters.dotnetArch }}
- template: /.pipelines/templates/insert-nuget-config-azfeed.yml@self
- pwsh: |
$repoRoot = "$(Build.SourcesDirectory)"
@@ -56,10 +90,29 @@ jobs:
$env:DOTNET_NOLOGO=1
$isEarlyAccess = '$(ISEARLYACCESS)'
$ADORepoUri = if ($isEarlyAccess -eq 'True')
{
$earlyAccessFeed = '$(EARLY_ACCESS_FEED)'
switch ($earlyAccessFeed) {
'net8' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-8-early-access/nuget/v3/index.json' }
'net9' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-9-early-access/nuget/v3/index.json' }
'net10' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-10-early-access/nuget/v3/index.json' }
'net11' { 'https://pkgs.dev.azure.com/powershell-rel/PowerShell/_packaging/powershell-net-11-early-access/nuget/v3/index.json' }
default { throw "Unknown early access feed URL: $earlyAccessFeed" }
}
}
else {
"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json"
}
Write-Verbose -Verbose "ADO Repo URI: $ADORepoUri"
$localLocation = "$(Pipeline.Workspace)/PSPackagesOfficial/drop_nupkg_build_nupkg"
$xmlElement = @"
<add key=`"local`" value=`"$localLocation`" />
<add key="dotnet" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v2" />
<add key=`"dotnet`" value=`"$ADORepoUri`" />
</packageSources>
"@
@@ -90,6 +143,7 @@ jobs:
displayName: Restore and execute tests
env:
__DOTNET_RUNTIME_FEED_KEY: $(RUNTIME_SOURCEFEED_KEY)
VSS_NUGET_EXTERNAL_FEED_ENDPOINTS: $(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)
- task: PublishTestResults@2
displayName: 'Publish Test Results **\test-hosting.xml'
+3 -3
View File
@@ -6,11 +6,11 @@ parameters:
steps:
- powershell: |
$shouldSign = $true
$authenticodeCert = 'CP-230012'
$msixCert = 'CP-230012'
$authenticodeCert = '$(authenticode_cert_id)'
$msixCert = '$(authenticode_cert_id)'
if($env:IS_DAILY -eq 'true')
{
$authenticodeCert = 'CP-460906'
$authenticodeCert = '$(authenticode_test_cert_id)'
}
if($env:SKIP_SIGNING -eq 'Yes')
{
@@ -0,0 +1,242 @@
parameters:
- name: RUN_WINDOWS
type: boolean
default: true
- name: RUN_TEST_AND_RELEASE
type: boolean
default: true
- name: OfficialBuild
type: boolean
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: EarlyAccessFeed
type: string
default: 'net10'
stages:
- stage: prep
jobs:
- job: SetVars
displayName: Set Variables
pool:
type: linux
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT/BuildJson'
- name: ob_sdl_codeSignValidation_enabled
value: false
- name: ob_sdl_codeql_compiled_enabled
value: false
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_signing_setup_enabled
value: false
- name: ob_sdl_sbom_enabled
value: false
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
steps:
- checkout: self
clean: true
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase
- pwsh: |
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: Capture environment variables
env:
ob_restore_phase: true # This ensures checkout is done at the beginning of the restore phase
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
CreateJson: yes
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
parameters:
DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
- stage: macos
displayName: macOS - build and sign
dependsOn: ['prep']
variables:
- name: ps_official_build
value: ${{ parameters.OfficialBuild }}
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
jobs:
- template: /.pipelines/templates/mac.yml@self
parameters:
buildArchitecture: x64
- template: /.pipelines/templates/mac.yml@self
parameters:
buildArchitecture: arm64
- stage: linux
displayName: linux - build and sign
dependsOn: ['prep']
variables:
- name: ps_official_build
value: ${{ parameters.OfficialBuild }}
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
jobs:
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-x64'
JobName: 'linux_x64'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-x64'
JobName: 'linux_x64_minSize'
BuildConfiguration: 'minSize'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-arm64'
JobName: 'linux_arm64_minSize'
BuildConfiguration: 'minSize'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-arm'
JobName: 'linux_arm'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-arm64'
JobName: 'linux_arm64'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-linux-x64'
JobName: 'linux_fxd_x64_mariner'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-linux-arm64'
JobName: 'linux_fxd_arm64_mariner'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent-noopt-linux-musl-x64'
JobName: 'linux_fxd_x64_alpine'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'fxdependent'
JobName: 'linux_fxd'
- template: /.pipelines/templates/linux.yml@self
parameters:
Runtime: 'linux-musl-x64'
JobName: 'linux_x64_alpine'
- stage: windows
displayName: windows - build and sign
dependsOn: ['prep']
condition: and(succeeded(),eq('${{ parameters.RUN_WINDOWS }}','true'))
variables:
- name: ps_official_build
value: ${{ parameters.OfficialBuild }}
- name: IsEarlyAccess
value: ${{ parameters.IsEarlyAccess }}
jobs:
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x64
BuildConfiguration: release
JobName: build_windows_x64_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x64
BuildConfiguration: minSize
JobName: build_windows_x64_minSize_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: arm64
BuildConfiguration: minSize
JobName: build_windows_arm64_minSize_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: x86
JobName: build_windows_x86_release
dotnetArch: 'win-x86'
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: arm64
JobName: build_windows_arm64_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: fxdependent
JobName: build_windows_fxdependent_release
- template: /.pipelines/templates/windows-hosted-build.yml@self
parameters:
Architecture: fxdependentWinDesktop
JobName: build_windows_fxdependentWinDesktop_release
- stage: test_and_release_artifacts
displayName: Test and Release Artifacts
dependsOn: ['prep']
condition: and(succeeded(),eq('${{ parameters.RUN_TEST_AND_RELEASE }}','true'))
jobs:
- template: /.pipelines/templates/testartifacts.yml@self
- job: release_json
displayName: Create and Upload release.json
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
- name: ob_sdl_tsa_configFile
value: $(Build.SourcesDirectory)\PowerShell\.config\tsaoptions.json
- name: ob_sdl_credscan_suppressionsFile
value: $(Build.SourcesDirectory)\PowerShell\.config\suppress.json
steps:
- checkout: self
clean: true
- template: /.pipelines/templates/SetVersionVariables.yml@self
parameters:
ReleaseTagVar: $(ReleaseTagVar)
- template: /.pipelines/templates/rebuild-branch-check.yml@self
- powershell: |
$metadata = Get-Content '$(Build.SourcesDirectory)/PowerShell/tools/metadata.json' -Raw | ConvertFrom-Json
# Use the rebuild branch check from the template
$isRebuildBranch = '$(RebuildBranchCheck.IsRebuildBranch)' -eq 'true'
# Don't mark as LTS release for rebuild branches
$LTS = $metadata.LTSRelease.Package -and -not $isRebuildBranch
if ($isRebuildBranch) {
Write-Verbose -Message "Rebuild branch detected, not marking as LTS release" -Verbose
}
@{ ReleaseVersion = "$(Version)"; LTSRelease = $LTS } | ConvertTo-Json | Out-File "$(Build.StagingDirectory)\release.json"
Get-Content "$(Build.StagingDirectory)\release.json"
if (-not (Test-Path "$(ob_outputDirectory)\metadata")) {
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\metadata"
}
Copy-Item -Path "$(Build.StagingDirectory)\release.json" -Destination "$(ob_outputDirectory)\metadata" -Force
displayName: Create and upload release.json file to build artifact
retryCountOnTaskFailure: 2
- template: /.pipelines/templates/step/finalize.yml@self
@@ -0,0 +1,249 @@
parameters:
- name: OfficialBuild
type: boolean
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: EarlyAccessFeed
type: string
default: 'net10'
stages:
- stage: prep
displayName: 'Prep BuildInfo+Az'
jobs:
- template: /.pipelines/templates/checkAzureContainer.yml@self
- stage: EarlyDotnet
displayName: 'Early .NET Setup'
dependsOn: []
condition: always()
jobs:
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
parameters:
DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
- ${{ else }}:
- job: skip_early_dotnet
displayName: 'Skip early access .NET setup'
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
steps:
- pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET setup.'
- stage: mac_package
displayName: 'macOS Pkg+Sign'
dependsOn: [EarlyDotnet]
jobs:
- template: /.pipelines/templates/mac-package-build.yml@self
parameters:
buildArchitecture: x64
OfficialBuild: ${{ parameters.OfficialBuild }}
- template: /.pipelines/templates/mac-package-build.yml@self
parameters:
buildArchitecture: arm64
OfficialBuild: ${{ parameters.OfficialBuild }}
- stage: windows_package_build
displayName: 'Win Pkg (unsigned)'
dependsOn: [EarlyDotnet]
jobs:
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: x64
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: arm64
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: x86
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: fxdependent
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: fxdependentWinDesktop
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: x64_minsize
- template: /.pipelines/templates/packaging/windows/package.yml@self
parameters:
runtime: arm64_minsize
- stage: windows_package_sign
displayName: 'Win Pkg Sign'
dependsOn: [windows_package_build]
jobs:
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: x64
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: arm64
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: x86
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: fxdependent
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: fxdependentWinDesktop
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: x64_minsize
- template: /.pipelines/templates/packaging/windows/sign.yml@self
parameters:
runtime: arm64_minsize
- stage: linux_package
displayName: 'Linux Pkg+Sign'
dependsOn: [EarlyDotnet]
jobs:
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: deb
jobName: deb
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm64'
signedDrop: 'drop_linux_sign_linux_arm64'
packageType: deb-arm64
jobName: deb_arm64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_x64_mariner'
signedDrop: 'drop_linux_sign_linux_fxd_x64_mariner'
packageType: rpm-fxdependent #mariner-x64
jobName: mariner_x64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_arm64_mariner'
signedDrop: 'drop_linux_sign_linux_fxd_arm64_mariner'
packageType: rpm-fxdependent-arm64 #mariner-arm64
jobName: mariner_arm64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: rpm
jobName: rpm
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm'
signedDrop: 'drop_linux_sign_linux_arm'
packageType: tar-arm
jobName: tar_arm
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm64'
signedDrop: 'drop_linux_sign_linux_arm64'
packageType: tar-arm64
jobName: tar_arm64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64_alpine'
signedDrop: 'drop_linux_sign_linux_x64_alpine'
packageType: tar-alpine
jobName: tar_alpine
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd'
signedDrop: 'drop_linux_sign_linux_fxd'
packageType: fxdependent
jobName: fxdependent
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64'
signedDrop: 'drop_linux_sign_linux_x64'
packageType: tar
jobName: tar
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_fxd_x64_alpine'
signedDrop: 'drop_linux_sign_linux_fxd_x64_alpine'
packageType: tar-alpine-fxdependent
jobName: tar_alpine_fxd
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_x64_minSize'
signedDrop: 'drop_linux_sign_linux_x64_minSize'
packageType: min-size-x64
jobName: minSize_x64
- template: /.pipelines/templates/linux-package-build.yml@self
parameters:
unsignedDrop: 'drop_linux_build_linux_arm64_minSize'
signedDrop: 'drop_linux_sign_linux_arm64_minSize'
packageType: min-size-arm64
jobName: minSize_arm64
- stage: nupkg
displayName: 'NuGet Pkg+Sign'
dependsOn: [EarlyDotnet]
jobs:
- template: /.pipelines/templates/nupkg.yml@self
- stage: msixbundle
displayName: 'MSIX Bundle+Sign'
dependsOn: [EarlyDotnet, windows_package_build] # Only depends on unsigned packages
jobs:
- template: /.pipelines/templates/package-create-msix.yml@self
parameters:
OfficialBuild: ${{ parameters.OfficialBuild }}
- stage: store_package
displayName: 'Store Package'
dependsOn: [msixbundle]
jobs:
- template: /.pipelines/templates/package-store-package.yml@self
- stage: upload
displayName: 'Upload'
dependsOn: [EarlyDotnet, prep, mac_package, windows_package_sign, linux_package, nupkg, msixbundle] # prep needed for BuildInfo JSON
jobs:
- template: /.pipelines/templates/uploadToAzure.yml@self
- stage: validatePackages
displayName: 'Validate Packages'
dependsOn: [upload]
jobs:
- template: /.pipelines/templates/release-validate-packagenames.yml@self
@@ -0,0 +1,400 @@
parameters:
- name: releaseEnvironment
type: string
- name: SkipPublish
type: boolean
- name: SkipPSInfraInstallers
type: boolean
- name: skipMSIXPublish
type: boolean
- name: IsEarlyAccess
type: boolean
default: false
- name: DOTNET_RUNTIME_VERSION
displayName: Runtime version of early access build
type: string
default: ' '
- name: DOTNET_SDK_VERSION
displayName: SDK version of early access build
type: string
default: ' '
- name: EarlyAccessFeed
type: string
default: 'net10'
stages:
- stage: setReleaseTagAndChangelog
displayName: 'Set Release Tag and Upload Changelog'
jobs:
- template: /.pipelines/templates/release-SetTagAndChangelog.yml@self
- stage: downloadDotnetEarlyAccess
displayName: 'Download Early release .NET'
jobs:
- ${{ if eq(parameters.IsEarlyAccess, true) }}:
- template: /.pipelines/templates/downloadDotnetEarlyAccess.yml@self
parameters:
DotnetRuntimeVersion: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DotnetSdkVersion: ${{ parameters.DOTNET_SDK_VERSION }}
- ${{ else }}:
- job: skip_download_dotnet_early_access
displayName: 'Skip early access .NET download'
pool:
type: windows
variables:
- name: ob_outputDirectory
value: '$(Build.ArtifactStagingDirectory)/ONEBRANCH_ARTIFACT'
steps:
- pwsh: Write-Host 'IsEarlyAccess is false; skipping early access .NET download.'
- stage: validateSdk
displayName: 'Validate SDK'
dependsOn: [downloadDotnetEarlyAccess]
jobs:
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "windowsSDK"
displayName: "Windows SDK Validation"
imageName: PSMMS2019-Secure
poolName: $(windowsPool)
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
dotnetArch: 'win-x64'
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "MacOSSDK"
displayName: "MacOS SDK Validation"
imageName: macOS-latest
poolName: Azure Pipelines
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
dotnetArch: 'osx-x64'
- template: /.pipelines/templates/release-validate-sdk.yml@self
parameters:
jobName: "LinuxSDK"
displayName: "Linux SDK Validation"
imageName: PSMMSUbuntu22.04-Secure
poolName: $(ubuntuPool)
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
EarlyAccessFeed: ${{ parameters.EarlyAccessFeed }}
dotnetArch: 'linux-x64'
- stage: gbltool
displayName: 'Validate Global tools'
dependsOn: [downloadDotnetEarlyAccess]
jobs:
- template: /.pipelines/templates/release-validate-globaltools.yml@self
parameters:
jobName: "WindowsGlobalTools"
displayName: "Windows Global Tools Validation"
jobtype: windows
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'win-x64'
- template: /.pipelines/templates/release-validate-globaltools.yml@self
parameters:
jobName: "LinuxGlobalTools"
displayName: "Linux Global Tools Validation"
jobtype: linux
globalToolExeName: 'pwsh'
globalToolPackageName: 'PowerShell.Linux.x64'
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'linux-x64'
- stage: fxdpackages
displayName: 'Validate FXD Packages'
dependsOn: [downloadDotnetEarlyAccess]
jobs:
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'winfxd'
displayName: 'Validate Win Fxd Packages'
jobtype: 'windows'
artifactName: 'drop_windows_package_package_win_fxdependent'
packageNamePattern: '**/*win-fxdependent.zip'
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'win-x64'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'winfxdDesktop'
displayName: 'Validate WinDesktop Fxd Packages'
jobtype: 'windows'
artifactName: 'drop_windows_package_package_win_fxdependentWinDesktop'
packageNamePattern: '**/*win-fxdependentwinDesktop.zip'
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'win-x64'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'linuxfxd'
displayName: 'Validate Linux Fxd Packages'
jobtype: 'linux'
artifactName: 'drop_linux_package_fxdependent'
packageNamePattern: '**/*linux-x64-fxdependent.tar.gz'
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'linux-x64'
- template: /.pipelines/templates/release-validate-fxdpackages.yml@self
parameters:
jobName: 'linuxArm64fxd'
displayName: 'Validate Linux ARM64 Fxd Packages'
jobtype: 'linux'
artifactName: 'drop_linux_package_fxdependent'
# this is really an architecture independent package
packageNamePattern: '**/*linux-x64-fxdependent.tar.gz'
arm64: 'yes'
enableCredScan: false
IsEarlyAccess: ${{ parameters.IsEarlyAccess }}
DOTNET_RUNTIME_VERSION: ${{ parameters.DOTNET_RUNTIME_VERSION }}
DOTNET_SDK_VERSION: ${{ parameters.DOTNET_SDK_VERSION }}
dotnetArch: 'linux-arm64'
- stage: ManualValidation
dependsOn: []
displayName: Manual Validation
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Validate OSX Packages
jobName: ValidateOsxPkg
instructions: |
Validate tar.gz package on osx-arm64
- stage: ReleaseAutomation
dependsOn: []
displayName: 'Release Automation'
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Start Release Automation
jobName: StartRA
instructions: |
Kick off Release automation build at: https://dev.azure.com/powershell-rel/Release-Automation/_build?definitionId=10&_a=summary
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Triage results
jobName: TriageRA
dependsOnJob: StartRA
instructions: |
Triage ReleaseAutomation results
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Signoff Tests
dependsOnJob: TriageRA
jobName: SignoffTests
instructions: |
Signoff ReleaseAutomation results
- stage: UpdateChangeLog
displayName: Update the changelog
dependsOn:
- ManualValidation
- ReleaseAutomation
- fxdpackages
- gbltool
- validateSdk
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make sure the changelog is updated
jobName: MergeChangeLog
instructions: |
Update and merge the changelog for the release.
This step is required for creating GitHub draft release.
- stage: PublishGitHubRelease
displayName: Publish GitHub
dependsOn:
- setReleaseTagAndChangelog
- UpdateChangeLog
variables:
ob_release_environment: ${{ parameters.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-github.yml@self
parameters:
skipPublish: ${{ parameters.SkipPublish }}
- stage: PushGitTagAndMakeDraftPublic
displayName: Push Git Tag and Make Draft Public
dependsOn: PublishGitHubRelease
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Push Git Tag
jobName: PushGitTag
instructions: |
Push the git tag to upstream
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make Draft Public
dependsOnJob: PushGitTag
jobName: DraftPublic
instructions: |
Make the GitHub Release Draft Public
- stage: PublishNugetRelease
displayName: Publish Nuget Release
dependsOn:
- setReleaseTagAndChangelog
- PushGitTagAndMakeDraftPublic
- UpdateChangeLog
variables:
ob_release_environment: ${{ parameters.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-Nuget.yml@self
parameters:
skipPublish: ${{ parameters.SkipPublish }}
- stage: BlobPublic
displayName: Make Blob Public
dependsOn:
- UpdateChangeLog
- PushGitTagAndMakeDraftPublic
jobs:
- template: /.pipelines/templates/release-MakeBlobPublic.yml@self
parameters:
SkipPSInfraInstallers: ${{ parameters.SkipPSInfraInstallers }}
- stage: PublishPMC
displayName: Publish PMC
dependsOn: PushGitTagAndMakeDraftPublic
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Publish to PMC
jobName: ReleaseToPMC
instructions: |
Run PowerShell-Release-Official-Azure.yml pipeline to publish to PMC
- stage: UpdateDotnetDocker
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Update DotNet SDK Docker images
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Update .NET SDK docker images
jobName: DotnetDocker
instructions: |
Create PR for updating dotnet-docker images to use latest PowerShell version.
1. Fork and clone https://github.com/dotnet/dotnet-docker.git
2. git checkout upstream/nightly -b updatePS
3. dotnet run --project .\eng\update-dependencies\ specific <dotnetversion> --product-version powershell=<powershellversion> --compute-shas
4. create PR targeting nightly branch
- stage: UpdateWinGet
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Add manifest entry to winget
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Add manifest entry to winget
jobName: UpdateWinGet
instructions: |
This is typically done by the community 1-2 days after the release.
- stage: PublishMsix
dependsOn:
- setReleaseTagAndChangelog
- PushGitTagAndMakeDraftPublic
displayName: Publish MSIX to store
variables:
ob_release_environment: ${{ parameters.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-MSIX-Publish.yml@self
parameters:
skipMSIXPublish: ${{ parameters.skipMSIXPublish }}
- stage: PublishVPack
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Release vPack
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Start 2 vPack Release pipelines
jobName: PublishVPack
instructions: |
1. Kick off PowerShell-vPack-Official pipeline
2. Kick off PowerShell-MSIXBundle-VPack pipeline
# Need to verify if the Az PS / CLI team still uses this. Skipping for this release.
# - stage: ReleaseDeps
# dependsOn: GitHubTasks
# displayName: Update pwsh.deps.json links
# jobs:
# - template: templates/release-UpdateDepsJson.yml
- stage: UploadBuildInfoJson
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Upload BuildInfo.json
jobs:
- template: /.pipelines/templates/release-upload-buildinfo.yml@self
- stage: ReleaseSymbols
dependsOn: PushGitTagAndMakeDraftPublic
displayName: Release Symbols
jobs:
- template: /.pipelines/templates/release-symbols.yml@self
- stage: ChangesToMaster
displayName: Ensure changes are in GH master
dependsOn:
- PublishPMC
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Make sure changes are in master
jobName: MergeToMaster
instructions: |
Make sure that changes README.md and metadata.json are merged into master on GitHub.
- stage: ReleaseToMU
displayName: Release to MU
dependsOn: PushGitTagAndMakeDraftPublic # This only needs the blob to be available
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Release to MU
instructions: |
Notify the PM team to start the process of releasing to MU.
- stage: ReleaseClose
displayName: Finish Release
dependsOn:
- ReleaseToMU
- ReleaseSymbols
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Retain Build
jobName: RetainBuild
instructions: |
Retain the build
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
displayName: Delete release branch
jobName: DeleteBranch
instructions: |
Delete release branch
Loaded 100 of 2485 files, more files were not shown because too many files have changed in this diff. Show more