Merge branch 'master' into copilot/address-inline-comment-feedback
No files matched your search
@@ -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>
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@"
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) }}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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/*
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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:
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
|
Before Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 13 KiB |
@@ -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>
|
||||
@@ -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">
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -14,8 +14,6 @@
|
||||
"qps-ploca",
|
||||
"qps-plocm"
|
||||
],
|
||||
"MediaRootPath": "",
|
||||
"MediaFallbackLanguage": "en-US",
|
||||
"PackagePath": [],
|
||||
"OutPath": "",
|
||||
"OutName": "",
|
||||
|
||||
@@ -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) ---"
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:"
|
||||
|
||||
@@ -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
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||