Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ jobs:
run: sudo apt update && sudo apt install musl-tools -y
- name: Build
shell: pwsh
run: ./build.ps1 -clippy -target x86_64-unknown-linux-musl
run: ./build.ps1 -clippy -architecture x86_64-unknown-linux-musl
- name: Run tests
shell: pwsh
run: ./build.ps1 -test -target x86_64-unknown-linux-musl
run: ./build.ps1 -test -architecture x86_64-unknown-linux-musl

build-windows:

Expand Down
68 changes: 67 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,79 @@ Please read the rest of this document to ensure a smooth contribution process.
* [GitHub Flow Guide](https://guides.github.com/introduction/flow/):
step-by-step instructions of GitHub Flow

## Contributing to Issues
## Issues for new contributors

* Check if the issue you are going to file already exists in our [GitHub issues](https://github.com/powershell/DSC/).
* If you can't find your issue already,
[open a new issue](https://github.com/PowerShell/DSC/issues/new/choose),
making sure to follow the directions as best you can.

## Contribution Workflow

Whether you’re fixing bugs, developing new functionality, or improving tests,
contributions are managed through a GitHub-centered workflow.
After setting up your GitHub account, follow these instructions:

1. Fork the repo you plan to work on.

In GitHub, click Fork on the project page to create your copy under your account.

1. Clone your fork locally

```powershell
git clone https://github.com/<your-github-username>/DSC.git
cd DSC
```

1. Add the upstream remote and sync main

```powershell
git remote add upstream https://github.com/PowerShell/DSC.git
git fetch upstream
git checkout main
git pull --ff-only upstream main
```

1. Create a new branch to hold your work.

```powershell
git checkout -b new-branch-name
```

1. Work on your new code. Write tests

```powershell
.\build.ps1 -UseCratesIO -Test
```

1. Commit your changes with a clear message

```powershell
git add -A
git commit -m "<concise summary of the change>"
```

1. Push your branch and open a Pull Request

```powershell
git push -u origin feature/<short-description>
```

In GitHub, open a PR from your branch to the upstream main branch. Link related issues
and include a brief summary and rationale.

1. Keep your branch up to date

```powershell
git fetch upstream
git rebase upstream/main
# resolve conflicts if any, then continue the rebase
git push --force-with-lease
```

> [!NOTE]
> `-UseCratesIO` ensures the build uses crates.io rather than internal replaced sources.

## Contributing to Documentation

### Contributing to documentation related to DSC
Expand Down
138 changes: 114 additions & 24 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,97 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

<#
.SYNOPSIS
Builds, tests, and packages the DSC executable for multiple platforms/architectures.

.DESCRIPTION
The .build.ps1 script performs the following tasks:

- Bootstraps required toolchains (Rust, Node.js, and optionally MSVC/Windows SDK).
- Builds all component crates and tools in dependency order using Cargo.
- Copies outputs into bin/<architecture>/<configuration>.
- Optionally runs static analysis (Clippy) and tests (Cargo/Pester).
- Creates distributable packages (MSIX/MSIXBundle/ZIP/TAR.GZ).
- Supports lockfile updates and dependency security auditing.

.PARAMETER Release
Builds with the Release configuration (default is Debug).

.PARAMETER architecture
Targets the platform to build and package for. Supported values:

- current
- aarch64-pc-windows-msvc
- x86_64-pc-windows-msvc
- aarch64-apple-darwin
- x86_64-apple-darwin
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl

Defaults to 'current'.

.PARAMETER Clippy
Run cargo clippy instead of building artifacts.

.PARAMETER SkipBuild
Skip building artifacts. Useful when you only want to package already-built outputs.

.PARAMETER packageType
Create a package from existing build outputs. One of: msix, msix-private, msixbundle, tgz, zip.
Note: When provided, the script will skip building; run a build first in a separate invocation.

.PARAMETER Test
Run tests after building. Executes cargo test per project and then Pester end-to-end tests.

.PARAMETER GetPackageVersion
Simply retrieves the current package version

.PARAMETER SkipLinkCheck
On Windows, skip checking/bootstrapping link.exe and C++ build tools.

.PARAMETER UseX64MakeAppx
On Arm64 Windows packaging, force use of x64 makeappx.exe.

.PARAMETER UseCratesIO
Use crates.io as the cargo registry (disables CFS source replacement).

.PARAMETER UpdateLockFile
Regenerate Cargo.lock files for projects that support it.

.PARAMETER Audit
Run cargo-audit (with automatic fixes when possible) before building.

.PARAMETER UseCFSAuth
Use Azure CLI to acquire an auth token for the CFS registry (requires az and az login).

.PARAMETER Clean
Run cargo clean in each project before building.

.EXAMPLE
PS> .\build.ps1 -UseCratesIO
Use crates.io as the cargo registry (disables CFS source replacement).

.EXAMPLE
PS> .\build.ps1 -Release
Build Release for the current host architecture and copy artifacts to bin\\release.

.EXAMPLE
PS> .\build.ps1 -Test
Build and run cargo tests for each project; then run Pester tests. Installs Pester and dependencies as needed.

.EXAMPLE
PS> .\build.ps1 -Release -architecture x86_64-pc-windows-msvc
PS> .\build.ps1 -packageType zip -architecture x86_64-pc-windows-msvc
Two-step Windows packaging: first build Release, then create a ZIP from existing outputs. Packaging skips building.

.EXAMPLE
PS> .\build.ps1 -GetPackageVersion
Print the current version
#>
[CmdletBinding()]
param(
[switch]$Release,
[ValidateSet('current','aarch64-pc-windows-msvc','x86_64-pc-windows-msvc','aarch64-apple-darwin','x86_64-apple-darwin','aarch64-unknown-linux-gnu','aarch64-unknown-linux-musl','x86_64-unknown-linux-gnu','x86_64-unknown-linux-musl')]
Expand All @@ -19,8 +110,7 @@ param(
[switch]$UpdateLockFile,
[switch]$Audit,
[switch]$UseCFSAuth,
[switch]$Clean,
[switch]$Verbose
[switch]$Clean
)

trap {
Expand Down Expand Up @@ -145,11 +235,11 @@ $filesToBeExecutable = @(
function Find-LinkExe {
try {
# this helper may not be needed anymore, but keeping in case the install doesn't work for everyone
Write-Verbose -Verbose "Finding link.exe"
Write-Verbose "Finding link.exe"
Push-Location $BuildToolsPath
Set-Location "$(Get-ChildItem -Directory | Sort-Object name -Descending | Select-Object -First 1)\bin\Host$($env:PROCESSOR_ARCHITECTURE)\x64" -ErrorAction Stop
$linkexe = (Get-Location).Path
Write-Verbose -Verbose "Using $linkexe"
Write-Verbose "Using $linkexe"
$linkexe
}
finally {
Expand Down Expand Up @@ -206,15 +296,15 @@ if ($null -ne $packageType) {
}

## Test if Rust is installed
if (!$usingADO -and !(Get-Command 'cargo' -ErrorAction Ignore)) {
Write-Verbose -Verbose "Rust not found, installing..."
if (!(Get-Command 'cargo' -ErrorAction Ignore)) {
Write-Verbose "Rust not found, installing..."
if (!$IsWindows) {
curl https://sh.rustup.rs -sSf | sh -s -- -y
$env:PATH += ":$env:HOME/.cargo/bin"
}
else {
Invoke-WebRequest 'https://static.rust-lang.org/rustup/dist/i686-pc-windows-gnu/rustup-init.exe' -OutFile 'temp:/rustup-init.exe'
Write-Verbose -Verbose "Use the default settings to ensure build works"
Write-Verbose "Use the default settings to ensure build works"
& 'temp:/rustup-init.exe' -y
$env:PATH += ";$env:USERPROFILE\.cargo\bin"
Remove-Item temp:/rustup-init.exe -ErrorAction Ignore
Expand All @@ -223,8 +313,8 @@ if ($null -ne $packageType) {
throw "Failed to install Rust"
}
}
elseif (!$usingADO) {
Write-Verbose -Verbose "Rust found, updating..."
else {
Write-Verbose "Rust found, updating..."
& $rustup update
}

Expand All @@ -239,7 +329,7 @@ if ($null -ne $packageType) {
## Test if Node is installed
## Skipping upgrade as users may have a specific version they want to use
if (!(Get-Command 'node' -ErrorAction Ignore)) {
Write-Verbose -Verbose "Node.js not found, installing..."
Write-Verbose "Node.js not found, installing..."
if (!$IsWindows) {
if (Get-Command 'brew' -ErrorAction Ignore) {
brew install node@24
Expand All @@ -249,7 +339,7 @@ if ($null -ne $packageType) {
}
else {
if (Get-Command 'winget' -ErrorAction Ignore) {
Write-Verbose -Verbose "Using winget to install Node.js"
Write-Verbose "Using winget to install Node.js"
winget install OpenJS.NodeJS --accept-source-agreements --accept-package-agreements --source winget --silent
} else {
Write-Warning "winget not found, please install Node.js manually"
Expand All @@ -276,15 +366,15 @@ if ($null -ne $packageType) {

if (!$SkipBuild -and !$SkipLinkCheck -and $IsWindows -and !(Get-Command 'link.exe' -ErrorAction Ignore)) {
if (!(Test-Path $BuildToolsPath)) {
Write-Verbose -Verbose "link.exe not found, installing C++ build tools"
Write-Verbose "link.exe not found, installing C++ build tools"
Invoke-WebRequest 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutFile 'temp:/vs_buildtools.exe'
$arg = @('--passive','--add','Microsoft.VisualStudio.Workload.VCTools','--includerecommended')
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
$arg += '--add','Microsoft.VisualStudio.Component.VC.Tools.ARM64'
}
Start-Process -FilePath 'temp:/vs_buildtools.exe' -ArgumentList $arg -Wait
Remove-Item temp:/vs_installer.exe -ErrorAction Ignore
Write-Verbose -Verbose "Updating env vars"
Write-Verbose "Updating env vars"
$machineEnv = [environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::Machine).Split(';')
$userEnv = [environment]::GetEnvironmentVariable("PATH", [System.EnvironmentVariableTarget]::User).Split(';')
$pathEnv = ($env:PATH).Split(';')
Expand Down Expand Up @@ -405,14 +495,14 @@ if (!$SkipBuild) {
{
if ($Clippy) {
if ($clippy_unclean_projects -contains $project) {
Write-Verbose -Verbose "Skipping clippy for $project"
Write-Verbose "Skipping clippy for $project"
}
elseif ($pedantic_unclean_projects -contains $project) {
Write-Verbose -Verbose "Running clippy for $project"
Write-Verbose "Running clippy for $project"
cargo clippy @flags -- -Dwarnings
}
else {
Write-Verbose -Verbose "Running clippy with pedantic for $project"
Write-Verbose "Running clippy with pedantic for $project"
cargo clippy @flags --% -- -Dwarnings -Dclippy::pedantic
}
}
Expand Down Expand Up @@ -568,7 +658,7 @@ if ($Test) {

foreach ($project in $projects) {
if ($IsWindows -and $skip_test_projects_on_windows -contains $project) {
Write-Verbose -Verbose "Skipping test for $project on Windows"
Write-Verbose "Skipping test for $project on Windows"
continue
}

Expand Down Expand Up @@ -667,7 +757,7 @@ if ($packageType -eq 'msixbundle') {
$isPreview = $productVersion -like '*-*'
$productName = "DesiredStateConfiguration"
if ($isPreview) {
Write-Verbose -Verbose "Preview version detected"
Write-Verbose "Preview version detected"
if ($isPrivate) {
$productName += "-Private"
}
Expand Down Expand Up @@ -698,7 +788,7 @@ if ($packageType -eq 'msixbundle') {
$productVersion += ".0"
}

Write-Verbose -Verbose "Product version is $productVersion"
Write-Verbose "Product version is $productVersion"
$arch = if ($architecture -eq 'aarch64-pc-windows-msvc') { 'arm64' } else { 'x64' }

# Appx manifest needs to be in root of source path, but the embedded version needs to be updated
Expand Down Expand Up @@ -739,21 +829,21 @@ if ($packageType -eq 'msixbundle') {
Copy-Item "$PSScriptRoot\packaging\assets\$asset.png" "$msixTarget\assets" -ErrorAction Stop
}

Write-Verbose "Creating priconfig.xml" -Verbose
Write-Verbose "Creating priconfig.xml"
& $makepri createconfig /o /cf (Join-Path $msixTarget "priconfig.xml") /dq en-US
if ($LASTEXITCODE -ne 0) {
throw "Failed to create priconfig.xml"
}

Write-Verbose "Creating resources.pri" -Verbose
Write-Verbose "Creating resources.pri"
Push-Location $msixTarget
& $makepri new /v /o /pr $msixTarget /cf (Join-Path $msixTarget "priconfig.xml")
Pop-Location
if ($LASTEXITCODE -ne 0) {
throw "Failed to create resources.pri"
}

Write-Verbose "Creating msix package" -Verbose
Write-Verbose "Creating msix package"

$targetFolder = Join-Path $PSScriptRoot 'bin' 'msix'
if (Test-Path $targetFolder) {
Expand All @@ -768,7 +858,7 @@ if ($packageType -eq 'msixbundle') {
throw "Failed to create msix package"
}

Write-Host -ForegroundColor Green "`nMSIX package is created at $packageName"
Write-Verbose "`nMSIX package is created at $packageName"
} elseif ($packageType -eq 'zip') {
$zipTarget = Join-Path $PSScriptRoot 'bin' $architecture 'zip'
if (Test-Path $zipTarget) {
Expand Down Expand Up @@ -822,7 +912,7 @@ if ($packageType -eq 'msixbundle') {
$architecture
}

Write-Verbose -Verbose "Creating tar.gz file"
Write-Verbose "Creating tar.gz file"
$packageName = "DSC-$productVersion-$productArchitecture.tar.gz"
$tarFile = Join-Path $PSScriptRoot 'bin' $packageName
tar -czvf $tarFile -C $tgzTarget .
Expand Down
Loading