<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://psake.dev/blog</id>
    <title>psake Blog</title>
    <updated>2026-04-15T12:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://psake.dev/blog"/>
    <subtitle>psake Blog</subtitle>
    <icon>https://psake.dev/img/favicon.ico</icon>
    <entry>
        <title type="html"><![CDATA[psake 5.0.0 Is Here: Declarative Tasks, Caching, and Structured Output]]></title>
        <id>https://psake.dev/blog/psake-5-0-0-released</id>
        <link href="https://psake.dev/blog/psake-5-0-0-released"/>
        <updated>2026-04-15T12:00:00.000Z</updated>
        <summary type="html"><![CDATA[psake 5.0.0 is a major leap forward for PowerShell build automation—bringing declarative task syntax, compile-time validation, file-based caching, structured output, and CI-native integrations.]]></summary>
        <content type="html"><![CDATA[<p>After years of steady iteration on the v4 line, we're thrilled to announce the release of <strong>psake 5.0.0</strong>—the biggest update to the PowerShell build automation framework since its inception. This release introduces a declarative task syntax, two-phase compilation, local file-based caching, structured output, and first-class CI integration. Here's everything that's new.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="declarative-task-syntax">Declarative Task Syntax<a href="https://psake.dev/blog/psake-5-0-0-released#declarative-task-syntax" class="hash-link" aria-label="Direct link to Declarative Task Syntax" title="Direct link to Declarative Task Syntax">​</a></h2>
<p>The flagship feature of psake 5 is a new hashtable-based syntax for defining tasks. Rather than relying on positional parameters, you can now describe tasks as structured data with named, validated keys:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Task </span><span class="token string" style="color:rgb(255, 121, 198)">'Build'</span><span class="token plain"> @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    DependsOn = </span><span class="token string" style="color:rgb(255, 121, 198)">'Clean'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Action    = </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> dotnet build </span><span class="token operator">-</span><span class="token plain">c </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Configuration</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Every key is validated at compile time—typos like <code>DependsOn</code> or <code>Action</code> are caught before a single task runs. The original parameter-based syntax still works, so your existing build scripts don't need to change.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="two-phase-compilation">Two-Phase Compilation<a href="https://psake.dev/blog/psake-5-0-0-released#two-phase-compilation" class="hash-link" aria-label="Direct link to Two-Phase Compilation" title="Direct link to Two-Phase Compilation">​</a></h2>
<p>psake 5 separates build file loading from task execution. When you call <code>Invoke-psake</code>, the dependency graph is built first via a topological sort, and circular dependencies are caught at <strong>compile time</strong> rather than halfway through a run. This means faster, clearer feedback—and no more builds that silently fail mid-execution.</p>
<p>You can also use the new <code>-CompileOnly</code> parameter to inspect the build plan without running anything:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">Invoke-psake</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">CompileOnly</span><br></span></code></pre></div></div>
<p>This is especially useful in code review and CI pre-flight checks.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="local-file-based-caching">Local File-Based Caching<a href="https://psake.dev/blog/psake-5-0-0-released#local-file-based-caching" class="hash-link" aria-label="Direct link to Local File-Based Caching" title="Direct link to Local File-Based Caching">​</a></h2>
<p>For tasks that process files—compilation, transpilation, packaging—psake 5 introduces content-addressed caching. Declare <code>Inputs</code> and <code>Outputs</code> on a task, and psake will SHA256-hash the inputs to determine whether the task actually needs to run:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Task </span><span class="token string" style="color:rgb(255, 121, 198)">'Build'</span><span class="token plain"> @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Inputs  = </span><span class="token string" style="color:rgb(255, 121, 198)">'src/**/*.cs'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'src/**/*.csproj'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Outputs = </span><span class="token string" style="color:rgb(255, 121, 198)">'bin/**/*.dll'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Action  = </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> dotnet build </span><span class="token operator">-</span><span class="token plain">c </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Configuration</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Cache state is stored in <code>.psake/cache/</code>. If nothing changed, the task is skipped and the build report marks it as <strong>Cached</strong>. To bypass caching for a single run, pass <code>-NoCache</code>:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token function" style="color:rgb(80, 250, 123)">Invoke-psake</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">NoCache</span><br></span></code></pre></div></div>
<p>And to clear the cache entirely, use the new <code>Clear-PsakeCache</code> function.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="structured-build-results">Structured Build Results<a href="https://psake.dev/blog/psake-5-0-0-released#structured-build-results" class="hash-link" aria-label="Direct link to Structured Build Results" title="Direct link to Structured Build Results">​</a></h2>
<p><code>Invoke-psake</code> now returns a <code>PsakeBuildResult</code> object containing per-task metrics, success status, duration, and error information. Scripting against build output no longer requires parsing console text:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$result</span><span class="token plain"> = </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-psake</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Tasks </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Where-Object</span><span class="token plain"> Cached </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Select-Object</span><span class="token plain"> Name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Duration</span><br></span></code></pre></div></div>
<p>The <code>$psake.build_success</code> variable is still set after every run, so existing CI scripts that check build status continue to work without modification.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="ci-native-output-formats">CI-Native Output Formats<a href="https://psake.dev/blog/psake-5-0-0-released#ci-native-output-formats" class="hash-link" aria-label="Direct link to CI-Native Output Formats" title="Direct link to CI-Native Output Formats">​</a></h2>
<p>Building for GitHub Actions? Pass <code>-OutputFormat GitHubActions</code> and psake will emit workflow annotations—warnings and errors that surface directly in pull request diffs. For pipelines that consume build data programmatically, <code>-OutputFormat JSON</code> outputs the full <code>PsakeBuildResult</code> as structured JSON.</p>
<p>The output format can also be set via the <code>PSAKE_OUTPUT_FORMAT</code> environment variable, making it easy to configure in CI without changing your build scripts.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="quiet-mode">Quiet Mode<a href="https://psake.dev/blog/psake-5-0-0-released#quiet-mode" class="hash-link" aria-label="Direct link to Quiet Mode" title="Direct link to Quiet Mode">​</a></h2>
<p>The new <code>-Quiet</code> parameter suppresses all console output while still returning the full <code>PsakeBuildResult</code> object—including complete error records for any failed tasks. No output is swallowed; it's simply not printed.</p>
<p>This is particularly valuable when psake is invoked by an LLM agent or AI coding tool. Console build logs are noisy: progress messages, separator lines, and timing output all burn through context that the model could spend on the actual problem. With <code>-Quiet</code>, the agent gets silence on stdout and a precise, structured result it can inspect programmatically:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$result</span><span class="token plain"> = </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-psake</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Quiet</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Success</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Full error records are available—no log scraping needed</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$result</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Tasks </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Where-Object</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Error </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">ForEach-Object</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Host</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Task '</span><span class="token string function" style="color:rgb(80, 250, 123)">$</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string function variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">Name</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string" style="color:rgb(255, 121, 198)">' failed: </span><span class="token string function" style="color:rgb(80, 250, 123)">$</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string function variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">Error</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">Message</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Rather than parsing wall-of-text build output, the agent can check <code>$result.Success</code>, iterate <code>$result.Tasks</code>, and read <code>$_.Error</code> directly—structured data that maps cleanly to a tool call response. Pair this with <code>-OutputFormat JSON</code> if you need to pass the result across a process boundary or into a prompt.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="new-testing-apis">New Testing APIs<a href="https://psake.dev/blog/psake-5-0-0-released#new-testing-apis" class="hash-link" aria-label="Direct link to New Testing APIs" title="Direct link to New Testing APIs">​</a></h2>
<p>Two new functions let you inspect and test your build scripts without running a full build:</p>
<ul>
<li><strong><code>Get-PsakeBuildPlan</code></strong> — Returns the full execution plan for a build file without running it. Inspect task order, dependencies, and caching configuration in tests.</li>
<li><strong><code>Test-PsakeTask</code></strong> — Executes a single named task with custom variable overrides. Great for unit-testing individual task logic in isolation.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="version-declaration">Version Declaration<a href="https://psake.dev/blog/psake-5-0-0-released#version-declaration" class="hash-link" aria-label="Direct link to Version Declaration" title="Direct link to Version Declaration">​</a></h2>
<p>Build files can now declare the minimum psake major version they require:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Version 5</span><br></span></code></pre></div></div>
<p>If someone runs your build script on an older psake installation, they get a clear error instead of a confusing failure deep inside a task.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hashtable-properties">Hashtable Properties<a href="https://psake.dev/blog/psake-5-0-0-released#hashtable-properties" class="hash-link" aria-label="Direct link to Hashtable Properties" title="Direct link to Hashtable Properties">​</a></h2>
<p>The <code>Properties</code> block gains a more concise hashtable syntax alongside the original scriptblock form:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Properties @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Configuration = </span><span class="token string" style="color:rgb(255, 121, 198)">'Release'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    OutputDir     = </span><span class="token string" style="color:rgb(255, 121, 198)">'./artifacts'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>
<p>Both styles are supported and can be mixed within the same build file.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="no_color-support"><code>NO_COLOR</code> Support<a href="https://psake.dev/blog/psake-5-0-0-released#no_color-support" class="hash-link" aria-label="Direct link to no_color-support" title="Direct link to no_color-support">​</a></h2>
<p>psake 5 respects the <code>$env:NO_COLOR</code> convention for suppressing colored output. Set it in environments where ANSI escape codes cause issues—terminals without color support, log aggregators, or accessibility tools.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-changes">Breaking Changes<a href="https://psake.dev/blog/psake-5-0-0-released#breaking-changes" class="hash-link" aria-label="Direct link to Breaking Changes" title="Direct link to Breaking Changes">​</a></h2>
<p>psake 5 is a major version, and it includes a few breaking changes. Most build scripts will work without modification, but there are three things to check:</p>
<ol>
<li><strong>Rename <code>default.ps1</code> to <code>psakefile.ps1</code></strong> — The <code>default.ps1</code> fallback file name is no longer auto-detected.</li>
<li><strong>Replace the wrapper scripts</strong> — <code>psake.ps1</code> and <code>psake.cmd</code> are removed. Use <code>Import-Module psake; Invoke-psake</code> instead.</li>
<li><strong>Update Framework calls</strong> — .NET Framework versions below 4.0 are no longer supported, and the default is now 4.7.2. The <code>$framework</code> global variable is removed; use <code>Framework '4.7.2'</code> instead.</li>
</ol>
<p>Additionally, the minimum required PowerShell version is now <strong>5.1</strong> (raised from 3.0), and the output handler configuration properties have been removed in favor of the new <code>-OutputFormat</code> and <code>-Quiet</code> parameters.</p>
<p>Full details are in the <a href="https://github.com/psake/psake/blob/master/docs/migration-v4-to-v5.md" target="_blank" rel="noopener noreferrer">migration guide</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="upgrading">Upgrading<a href="https://psake.dev/blog/psake-5-0-0-released#upgrading" class="hash-link" aria-label="Direct link to Upgrading" title="Direct link to Upgrading">​</a></h2>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Install from the PowerShell Gallery</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">Install-Module</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name psake </span><span class="token operator">-</span><span class="token plain">MinimumVersion 5</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">0 </span><span class="token operator">-</span><span class="token plain">Force</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Verify the version</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token function" style="color:rgb(80, 250, 123)">Get-Module</span><span class="token plain"> psake </span><span class="token operator">-</span><span class="token plain">ListAvailable </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Select-Object</span><span class="token plain"> Version</span><br></span></code></pre></div></div>
<p>Then run your existing build to check for any breaking changes. For most projects, it'll just work.</p>
<hr>
<p>psake 5 is the result of years of community feedback, and we're excited to see what you build with it. If you run into anything unexpected, <a href="https://github.com/psake/psake/issues" target="_blank" rel="noopener noreferrer">open an issue</a>. And if you're using the new features in interesting ways, we'd love to hear about it.</p>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
        <category label="Release" term="Release"/>
        <category label="Announcement" term="Announcement"/>
        <category label="psake" term="psake"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="Build Automation" term="Build Automation"/>
        <category label="CI/CD" term="CI/CD"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Building a Resilient build.ps1 for psake Projects]]></title>
        <id>https://psake.dev/blog/resilient-build-ps1</id>
        <link href="https://psake.dev/blog/resilient-build-ps1"/>
        <updated>2026-04-08T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[Extend your psake build.ps1 with clear error handling, dynamic tab completion, CI-safe module imports, and more.]]></summary>
        <content type="html"><![CDATA[<p>In psake projects, a <code>build.ps1</code> is the conventional entry point script that wires everything together. It installs dependencies, configures the environment, and hands off to psake to run your actual build tasks. Think of it as the bootstrapper that gets a fresh machine — or a CI agent — from zero to a working build in a single command: <code>.\build.ps1</code>.</p>
<p>psake itself doesn't ship a <code>build.ps1</code> — it's a best practice that most projects adopt. A typical starter script covers the basics: bootstrap installation, help output, build environment detection, and proper CI exit codes. But once you're running concurrent CI jobs, managing internal package feeds, or onboarding new contributors, a few gaps start to show.</p>
<p>The script below addresses those gaps with clear error handling, dynamic tab completion, CI-safe module imports, internal repository support, and PowerShellGet version pinning. I cover each pattern in detail in the <a href="https://tablackburn.github.io/p/resilient-build-ps1/" target="_blank" rel="noopener noreferrer">full post on my blog</a> — but here's the complete script. Copy it into your project and adjust the repository name and URL to match your environment:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Diagnostics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CodeAnalysis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SuppressMessageAttribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'PSReviewUnusedParameter'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'Command'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Justification = </span><span class="token string" style="color:rgb(255, 121, 198)">'false positive'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Diagnostics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CodeAnalysis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SuppressMessageAttribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'PSReviewUnusedParameter'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'Parameter'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Justification = </span><span class="token string" style="color:rgb(255, 121, 198)">'false positive'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Diagnostics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CodeAnalysis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SuppressMessageAttribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'PSReviewUnusedParameter'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'CommandAst'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Justification = </span><span class="token string" style="color:rgb(255, 121, 198)">'false positive'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">Diagnostics</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CodeAnalysis</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">SuppressMessageAttribute</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'PSReviewUnusedParameter'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token string" style="color:rgb(255, 121, 198)">'FakeBoundParams'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    Justification = </span><span class="token string" style="color:rgb(255, 121, 198)">'false positive'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">CmdletBinding</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">DefaultParameterSetName = </span><span class="token string" style="color:rgb(255, 121, 198)">'task'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">param</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">parameter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ParameterSetName = </span><span class="token string" style="color:rgb(255, 121, 198)">'task'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Position = 0</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">ArgumentCompleter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">param</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Command</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Parameter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$WordToComplete</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$CommandAst</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$FakeBoundParams</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token function" style="color:rgb(80, 250, 123)">Get-PSakeScriptTasks</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">BuildFile </span><span class="token string" style="color:rgb(255, 121, 198)">'./psakeFile.ps1'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ErrorAction </span><span class="token string" style="color:rgb(255, 121, 198)">'Stop'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token function" style="color:rgb(80, 250, 123)">Where-Object</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Name </span><span class="token operator">-like</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$WordToComplete</span><span class="token string" style="color:rgb(255, 121, 198)">*"</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token function" style="color:rgb(80, 250, 123)">Select-Object</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ExpandProperty </span><span class="token string" style="color:rgb(255, 121, 198)">'Name'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token namespace">[string[]]</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Task</span><span class="token plain"> = </span><span class="token string" style="color:rgb(255, 121, 198)">'default'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token namespace">[switch]</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Bootstrap</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain">parameter</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">ParameterSetName = </span><span class="token string" style="color:rgb(255, 121, 198)">'Help'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token namespace">[switch]</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Help</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$ErrorActionPreference</span><span class="token plain"> = </span><span class="token string" style="color:rgb(255, 121, 198)">'Stop'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$psakeFile</span><span class="token plain"> = </span><span class="token string" style="color:rgb(255, 121, 198)">'./psakeFile.ps1'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Bootstrap</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Patch TLS protocols for older Windows versions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token namespace">[System.Net.ServicePointManager]</span><span class="token plain">::SecurityProtocol = </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token namespace">[System.Net.ServicePointManager]</span><span class="token plain">::SecurityProtocol </span><span class="token operator">-bor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token namespace">[System.Net.SecurityProtocolType]</span><span class="token plain">::Tls12 </span><span class="token operator">-bor</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token namespace">[System.Net.SecurityProtocolType]</span><span class="token plain">::Tls13</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Get-PackageProvider</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'Nuget'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ForceBootstrap </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">Out-Null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Set-PSRepository</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'PSGallery'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">InstallationPolicy </span><span class="token string" style="color:rgb(255, 121, 198)">'Trusted'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Pin PowerShellGet to v2</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$powerShellGetModule</span><span class="token plain"> = </span><span class="token function" style="color:rgb(80, 250, 123)">Get-Module</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'PowerShellGet'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ListAvailable </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Where-Object</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Version</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Major </span><span class="token operator">-eq</span><span class="token plain"> 2 </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Sort-Object</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Property </span><span class="token string" style="color:rgb(255, 121, 198)">'Version'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Descending </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Select-Object</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">First 1</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$powerShellGetModuleParameters</span><span class="token plain"> = @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Name           = </span><span class="token string" style="color:rgb(255, 121, 198)">'PowerShellGet'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        MinimumVersion = </span><span class="token string" style="color:rgb(255, 121, 198)">'2.0.0'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        MaximumVersion = </span><span class="token string" style="color:rgb(255, 121, 198)">'2.99.99'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Force          = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$powerShellGetModule</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Install-Module</span><span class="token plain"> @powerShellGetModuleParameters </span><span class="token operator">-</span><span class="token plain">Scope </span><span class="token string" style="color:rgb(255, 121, 198)">'CurrentUser'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">AllowClobber</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Import-Module</span><span class="token plain"> @powerShellGetModuleParameters</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Register internal repository (idempotent)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryName</span><span class="token plain"> = </span><span class="token string" style="color:rgb(255, 121, 198)">'internal-nuget-repo'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">Get-PSRepository</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryName</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ErrorAction </span><span class="token string" style="color:rgb(255, 121, 198)">'SilentlyContinue'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryUrl</span><span class="token plain"> = </span><span class="token string" style="color:rgb(255, 121, 198)">"https://nuget.example.com/api/v2/</span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryName</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$registerPSRepositorySplat</span><span class="token plain"> = @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            Name                      = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryName</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            SourceLocation            = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryUrl</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            PublishLocation           = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryUrl</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            ScriptSourceLocation      = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$repositoryUrl</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            InstallationPolicy        = </span><span class="token string" style="color:rgb(255, 121, 198)">'Trusted'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            PackageManagementProvider = </span><span class="token string" style="color:rgb(255, 121, 198)">'NuGet'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Register-PSRepository</span><span class="token plain"> @registerPSRepositorySplat</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Install PSDepend if missing</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">Get-Module</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'PSDepend'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ListAvailable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Install-Module</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'PSDepend'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Repository </span><span class="token string" style="color:rgb(255, 121, 198)">'PSGallery'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Scope </span><span class="token string" style="color:rgb(255, 121, 198)">'CurrentUser'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Force</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token comment" style="color:rgb(98, 114, 164)"># Try-import-first pattern</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$psDependParameters</span><span class="token plain"> = @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Path          = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSScriptRoot</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Recurse       = </span><span class="token boolean">$False</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        WarningAction = </span><span class="token string" style="color:rgb(255, 121, 198)">'SilentlyContinue'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Import        = </span><span class="token boolean">$True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        Force         = </span><span class="token boolean">$True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        ErrorAction   = </span><span class="token string" style="color:rgb(255, 121, 198)">'Stop'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$importSucceeded</span><span class="token plain"> = </span><span class="token boolean">$false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-PSDepend</span><span class="token plain"> @psDependParameters</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$importSucceeded</span><span class="token plain"> = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Verbose</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Successfully imported existing modules.'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Verbose</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Verbose</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Could not import all required modules: </span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Verbose</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Verbose</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Attempting to install missing or outdated dependencies...'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Verbose</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$importSucceeded</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">try</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-PSDepend</span><span class="token plain"> @psDependParameters </span><span class="token operator">-</span><span class="token plain">Install</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Error</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Failed to install and import required dependencies: </span><span class="token string variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Error</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'This may be due to locked module files. Please restart the build environment or clear module locks.'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Exception</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">InnerException</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">                </span><span class="token function" style="color:rgb(80, 250, 123)">Write-Error</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"Inner exception: </span><span class="token string function" style="color:rgb(80, 250, 123)">$</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string function variable" style="color:rgb(189, 147, 249);font-style:italic">$_</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">Exception</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">InnerException</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token string function" style="color:rgb(80, 250, 123)">Message</span><span class="token string function punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token string" style="color:rgb(255, 121, 198)">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">            </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">Get-Module</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'PSDepend'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">ListAvailable</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">throw</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Missing dependencies. Please run with the "-Bootstrap" flag to install dependencies.'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-PSDepend</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Path </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSScriptRoot</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Recurse </span><span class="token boolean">$False</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">WarningAction </span><span class="token string" style="color:rgb(255, 121, 198)">'SilentlyContinue'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Import </span><span class="token operator">-</span><span class="token plain">Force</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">if</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSCmdlet</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">ParameterSetName </span><span class="token operator">-eq</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">'Help'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Get-PSakeScriptTasks</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">buildFile </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$psakeFile</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">        </span><span class="token function" style="color:rgb(80, 250, 123)">Format-Table</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Property Name</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Description</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> Alias</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> DependsOn</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">else</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Set-BuildEnvironment</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Force</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Invoke-psake</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">buildFile </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$psakeFile</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">taskList </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$Task</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">nologo</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">exit</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token namespace">[int]</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token operator">-not</span><span class="token plain"> </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$psake</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">build_success</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre></div></div>]]></content>
        <author>
            <name>Trent Blackburn</name>
            <uri>https://tablackburn.github.io</uri>
        </author>
        <category label="psake" term="psake"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="Build Automation" term="Build Automation"/>
        <category label="CI/CD" term="CI/CD"/>
        <category label="Best Practices" term="Best Practices"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[psake Meets VS Code: The Official Extension Hits v1.0]]></title>
        <id>https://psake.dev/blog/psake-vscode-extension-v1</id>
        <link href="https://psake.dev/blog/psake-vscode-extension-v1"/>
        <updated>2026-03-10T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[The psake VS Code extension v1.0 brings task discovery, CodeLens integration, a dedicated task explorer, and smart build script detection directly into your editor.]]></summary>
        <content type="html"><![CDATA[<p>We're thrilled to announce the v1.0 release of the <a href="https://github.com/psake/psake-vscode" target="_blank" rel="noopener noreferrer">psake VS Code extension</a>—bringing first-class psake support directly into the world's most popular code editor. If you've been running psake from the terminal, you can now discover, navigate, and execute your build tasks without ever leaving VS Code.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-a-vs-code-extension">Why a VS Code Extension?<a href="https://psake.dev/blog/psake-vscode-extension-v1#why-a-vs-code-extension" class="hash-link" aria-label="Direct link to Why a VS Code Extension?" title="Direct link to Why a VS Code Extension?">​</a></h2>
<p>A core part of our mission with psake is meeting developers where they already work. Whether that's through <a href="https://psake.dev/blog/introducing-psake-agent-skill">AI-assisted workflows with Agent Skills</a>, CI/CD pipelines, or your daily editor—we want psake to feel native to your environment. With VS Code being the editor of choice for so many PowerShell developers, a dedicated extension was a natural next step.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-in-v10">What's in v1.0<a href="https://psake.dev/blog/psake-vscode-extension-v1#whats-in-v10" class="hash-link" aria-label="Direct link to What's in v1.0" title="Direct link to What's in v1.0">​</a></h2>
<p>This isn't a minimal snippet pack. The v1.0 release is a full-featured integration that makes VS Code aware of your psake build system.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="task-provider">Task Provider<a href="https://psake.dev/blog/psake-vscode-extension-v1#task-provider" class="hash-link" aria-label="Direct link to Task Provider" title="Direct link to Task Provider">​</a></h3>
<p>The extension automatically detects tasks from your <code>psakefile.ps1</code> and surfaces them in VS Code's built-in task system. Your default task maps to the Build group, so <code>Ctrl+Shift+B</code> just works. Tasks refresh automatically when you save your build file—no manual reload needed.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="psake-tasks-explorer">psake Tasks Explorer<a href="https://psake.dev/blog/psake-vscode-extension-v1#psake-tasks-explorer" class="hash-link" aria-label="Direct link to psake Tasks Explorer" title="Direct link to psake Tasks Explorer">​</a></h3>
<p>A dedicated sidebar panel in the Explorer view gives you an at-a-glance view of every task in your project, complete with descriptions and dependency chains. Click any task to navigate directly to its definition, or hit the run button to execute it immediately.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="codelens-integration">CodeLens Integration<a href="https://psake.dev/blog/psake-vscode-extension-v1#codelens-integration" class="hash-link" aria-label="Direct link to CodeLens Integration" title="Direct link to CodeLens Integration">​</a></h3>
<p>Every <code>Task</code> declaration in your build file gets a "Run Task" CodeLens action. See a task, run it—right from the editor gutter. It's the fastest path from reading build logic to executing it.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="smart-build-script-detection">Smart Build Script Detection<a href="https://psake.dev/blog/psake-vscode-extension-v1#smart-build-script-detection" class="hash-link" aria-label="Direct link to Smart Build Script Detection" title="Direct link to Smart Build Script Detection">​</a></h3>
<p>If your project uses a wrapper script like <code>build.ps1</code> (a common pattern in the psake ecosystem), the extension detects it automatically and routes task execution through it. This means your bootstrapping, dependency installation, and any custom setup all run correctly—just as they would from the terminal.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="tasksjson-intellisense">tasks.json IntelliSense<a href="https://psake.dev/blog/psake-vscode-extension-v1#tasksjson-intellisense" class="hash-link" aria-label="Direct link to tasks.json IntelliSense" title="Direct link to tasks.json IntelliSense">​</a></h3>
<p>When you configure psake tasks in <code>.vscode/tasks.json</code>, the extension provides autocomplete for task names. Combined with the new "psake: Sync Tasks to tasks.json" command, you can quickly wire up your build tasks into VS Code's task runner with full IntelliSense support.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="nine-code-snippets">Nine Code Snippets<a href="https://psake.dev/blog/psake-vscode-extension-v1#nine-code-snippets" class="hash-link" aria-label="Direct link to Nine Code Snippets" title="Direct link to Nine Code Snippets">​</a></h3>
<p>Scaffolding new tasks and build file structures is faster with nine built-in snippets covering everything from basic task definitions to <code>Properties</code>, <code>Include</code>, <code>Framework</code>, <code>FormatTaskName</code>, <code>TaskSetup</code>, and <code>TaskTearDown</code> blocks.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="quick-start">Quick Start<a href="https://psake.dev/blog/psake-vscode-extension-v1#quick-start" class="hash-link" aria-label="Direct link to Quick Start" title="Direct link to Quick Start">​</a></h2>
<ol>
<li>Install the <a href="https://marketplace.visualstudio.com/publishers/psake" target="_blank" rel="noopener noreferrer">psake extension</a> from the VS Code Marketplace</li>
<li>Make sure you have the <a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell" target="_blank" rel="noopener noreferrer">PowerShell extension</a> installed</li>
<li>Open a project that contains a <code>psakefile.ps1</code> or <code>build.ps1</code></li>
<li>The extension activates automatically—check the Explorer sidebar for the psake Tasks panel</li>
</ol>
<p>That's it. No configuration required—but there's plenty available if you need it.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="fully-configurable">Fully Configurable<a href="https://psake.dev/blog/psake-vscode-extension-v1#fully-configurable" class="hash-link" aria-label="Direct link to Fully Configurable" title="Direct link to Fully Configurable">​</a></h2>
<p>The extension works out of the box, but every aspect of its behavior can be tuned to fit your workflow. Toggle CodeLens on or off, point to a custom PowerShell executable, pass extra parameters to <code>Invoke-psake</code> or your build script, and customize shell arguments—all without restarting VS Code.</p>
<p>For the full list of settings, check out the <a href="https://psake.dev/docs/integrations/vscode-extension#configuration">VS Code extension docs</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="part-of-a-growing-ecosystem">Part of a Growing Ecosystem<a href="https://psake.dev/blog/psake-vscode-extension-v1#part-of-a-growing-ecosystem" class="hash-link" aria-label="Direct link to Part of a Growing Ecosystem" title="Direct link to Part of a Growing Ecosystem">​</a></h2>
<p>The VS Code extension joins a growing set of tools designed to make psake easy to use wherever you are:</p>
<ul>
<li><strong><a href="https://github.com/psake/psake" target="_blank" rel="noopener noreferrer">psake</a></strong> — The build automation engine</li>
<li><strong><a href="https://github.com/psake/PowerShellBuild" target="_blank" rel="noopener noreferrer">PowerShellBuild</a></strong> — Common build tasks for PowerShell modules</li>
<li><strong><a href="https://github.com/psake/psake-llm-tools" target="_blank" rel="noopener noreferrer">psake Agent Skill</a></strong> — AI-assisted psake expertise for Claude and GitHub Copilot</li>
<li><strong><a href="https://github.com/psake/psake-vscode" target="_blank" rel="noopener noreferrer">psake VS Code Extension</a></strong> — First-class editor integration</li>
</ul>
<p>We're committed to making psake feel at home in every part of your development workflow. If you have ideas for where psake should go next, <a href="https://github.com/psake/psake-vscode/issues" target="_blank" rel="noopener noreferrer">open an issue</a> or join the conversation.</p>
<p>Give the extension a try and let us know what you think!</p>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
        <category label="Announcement" term="Announcement"/>
        <category label="Release" term="Release"/>
        <category label="psake" term="psake"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="VS Code" term="VS Code"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[PowerShellBuild v0.8.0: Authenticode Signing & New Documentation]]></title>
        <id>https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs</id>
        <link href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs"/>
        <updated>2026-02-21T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[PowerShellBuild v0.8.0 brings Authenticode code-signing support for PowerShell modules, and comprehensive docs are now available on the psake docs site.]]></summary>
        <content type="html"><![CDATA[<p>Two exciting updates to share today: <strong>PowerShellBuild v0.8.0</strong> has been released with built-in Authenticode code-signing support, and we've added a comprehensive <a href="https://psake.dev/docs/powershellbuild/introduction">PowerShellBuild documentation section</a> right here on the psake docs site.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="powershellbuild-docs-are-now-on-the-psake-site">PowerShellBuild Docs Are Now on the psake Site<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#powershellbuild-docs-are-now-on-the-psake-site" class="hash-link" aria-label="Direct link to PowerShellBuild Docs Are Now on the psake Site" title="Direct link to PowerShellBuild Docs Are Now on the psake Site">​</a></h2>
<p>If you've been looking for guidance on using PowerShellBuild to streamline your PowerShell module builds, you no longer need to piece things together from the README alone. The psake docs site now has a dedicated <strong>PowerShellBuild</strong> section covering:</p>
<ul>
<li><a href="https://psake.dev/docs/powershellbuild/introduction"><strong>Introduction</strong></a> — What PowerShellBuild is and how it relates to psake</li>
<li><a href="https://psake.dev/docs/powershellbuild/getting-started"><strong>Getting Started</strong></a> — Installation and first-build walkthrough</li>
<li><a href="https://psake.dev/docs/powershellbuild/configuration"><strong>Configuration</strong></a> — Deep dive into <code>$PSBPreference</code> and how to customize every aspect of your build</li>
<li><a href="https://psake.dev/docs/powershellbuild/task-reference"><strong>Task Reference</strong></a> — Complete listing of all available tasks and their dependencies</li>
<li><a href="https://psake.dev/docs/powershellbuild/real-world-example"><strong>Real-World Example</strong></a> — A practical end-to-end project setup</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-new-in-v080--authenticode-signing">What's New in v0.8.0 — Authenticode Signing<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#whats-new-in-v080--authenticode-signing" class="hash-link" aria-label="Direct link to What's New in v0.8.0 — Authenticode Signing" title="Direct link to What's New in v0.8.0 — Authenticode Signing">​</a></h2>
<p>The headline feature in <a href="https://github.com/psake/PowerShellBuild/releases/tag/v0.8.0" target="_blank" rel="noopener noreferrer">PowerShellBuild v0.8.0</a> is full Authenticode code-signing support for PowerShell modules. This was a highly requested capability, and it's now baked right into the standard build pipeline.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="three-new-public-functions">Three New Public Functions<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#three-new-public-functions" class="hash-link" aria-label="Direct link to Three New Public Functions" title="Direct link to Three New Public Functions">​</a></h3>
<p><strong><code>Get-PSBuildCertificate</code></strong> resolves a code-signing <code>X509Certificate2</code> from five different sources:</p>
<ul>
<li><strong>Auto</strong> — Automatically detects from environment variables or the certificate store</li>
<li><strong>Windows certificate store</strong> — With optional thumbprint filtering</li>
<li><strong>Base64-encoded PFX</strong> — From environment variables, ideal for CI/CD pipelines</li>
<li><strong>PFX file on disk</strong> — With optional password protection</li>
<li><strong>Pre-resolved certificate object</strong> — For custom providers like Azure Key Vault</li>
</ul>
<p><strong><code>Invoke-PSBuildModuleSigning</code></strong> signs your module files (<code>.psd1</code>, <code>.psm1</code>, <code>.ps1</code>) with Authenticode signatures. It supports configurable timestamp servers and hash algorithms including SHA256, SHA384, and SHA512.</p>
<p><strong><code>New-PSBuildFileCatalog</code></strong> creates Windows catalog (<code>.cat</code>) files that record cryptographic hashes of your module's contents for tamper detection.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="four-new-build-tasks">Four New Build Tasks<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#four-new-build-tasks" class="hash-link" aria-label="Direct link to Four New Build Tasks" title="Direct link to Four New Build Tasks">​</a></h3>
<table><thead><tr><th>Task</th><th>Description</th></tr></thead><tbody><tr><td><code>SignModule</code></td><td>Signs module files with Authenticode</td></tr><tr><td><code>BuildCatalog</code></td><td>Creates a Windows catalog file</td></tr><tr><td><code>SignCatalog</code></td><td>Signs the catalog file</td></tr><tr><td><code>Sign</code></td><td>Meta-task that orchestrates the full signing pipeline</td></tr></tbody></table>
<p>These tasks slot into the existing build pipeline with proper dependency ordering: <strong>Build → SignModule → BuildCatalog → SignCatalog</strong>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="certificate-sources">Certificate Sources<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#certificate-sources" class="hash-link" aria-label="Direct link to Certificate Sources" title="Direct link to Certificate Sources">​</a></h2>
<p>PowerShellBuild supports four ways to supply a certificate, listed here in order of common use:</p>
<p><strong>1. Automatic (CI/CD) — Base64 PFX in an env var</strong></p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Store your PFX as a base64 secret (e.g. GitHub Actions secret SIGNCERTIFICATE)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># PowerShellBuild picks it up automatically when Sign.Enabled = $true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Enabled = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># CertificateSource defaults to 'Auto' — done</span><br></span></code></pre></div></div>
<p><strong>2. Local dev — certificate store</strong></p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Enabled           = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CertificateSource = </span><span class="token string" style="color:rgb(255, 121, 198)">'Store'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># picks first valid, unexpired code-signing cert in Cert:\CurrentUser\My</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Or pin to a specific one by thumbprint:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CertificateSource = </span><span class="token string" style="color:rgb(255, 121, 198)">'Thumbprint'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Thumbprint        = </span><span class="token string" style="color:rgb(255, 121, 198)">'AB12CD34EF...'</span><br></span></code></pre></div></div>
<p><strong>3. PFX file on disk</strong></p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Enabled           = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">CertificateSource = </span><span class="token string" style="color:rgb(255, 121, 198)">'PfxFile'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">PfxFilePath       = </span><span class="token string" style="color:rgb(255, 121, 198)">'./codesign.pfx'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">PfxFilePassword   = </span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token function" style="color:rgb(80, 250, 123)">Read-Host</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">AsSecureString </span><span class="token string" style="color:rgb(255, 121, 198)">'Password'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p><strong>4. Pre-resolved object (Azure Key Vault, HSM, etc.)</strong></p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Get the cert however you like, then hand it directly:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$cert</span><span class="token plain"> = </span><span class="token function" style="color:rgb(80, 250, 123)">Get-AzKeyVaultCertificate</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">VaultName </span><span class="token string" style="color:rgb(255, 121, 198)">'MyVault'</span><span class="token plain"> </span><span class="token operator">-</span><span class="token plain">Name </span><span class="token string" style="color:rgb(255, 121, 198)">'CodeSignCert'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">    </span><span class="token function" style="color:rgb(80, 250, 123)">Get-AzKeyVaultSecret</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)"># your Key Vault retrieval logic</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Enabled     = </span><span class="token boolean">$true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPreference</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Sign</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">Certificate = </span><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$cert</span><span class="token plain">   </span><span class="token comment" style="color:rgb(98, 114, 164)"># bypasses CertificateSource entirely</span><br></span></code></pre></div></div>
<p>All of these go in your <code>Properties {}</code> block (psake) or before dot-sourcing (Invoke-Build), before the task file is loaded. To also sign before publishing:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:#282A36"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#F8F8F2;background-color:#282A36"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#F8F8F2"><span class="token variable" style="color:rgb(189, 147, 249);font-style:italic">$PSBPublishDependency</span><span class="token plain"> = @</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token string" style="color:rgb(255, 121, 198)">'Sign'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre></div></div>
<p>All signing operations include platform checks (Windows-only) with appropriate warnings, and verbose logging throughout makes troubleshooting straightforward.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="get-started">Get Started<a href="https://psake.dev/blog/powershellbuild-v0.8.0-signing-and-docs#get-started" class="hash-link" aria-label="Direct link to Get Started" title="Direct link to Get Started">​</a></h2>
<ul>
<li><strong>Read the docs:</strong> Check out the <a href="https://psake.dev/docs/powershellbuild/introduction">PowerShellBuild documentation</a> for a complete walkthrough</li>
<li><strong>Upgrade:</strong> <code>Install-Module PowerShellBuild -RequiredVersion 0.8.0</code></li>
<li><strong>Release notes:</strong> <a href="https://github.com/psake/PowerShellBuild/releases/tag/v0.8.0" target="_blank" rel="noopener noreferrer">v0.8.0 on GitHub</a></li>
<li><strong>Feedback:</strong> Open an issue on <a href="https://github.com/psake/PowerShellBuild/issues" target="_blank" rel="noopener noreferrer">GitHub</a> — we'd love to hear how you're using the signing tasks</li>
</ul>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
        <category label="Announcement" term="Announcement"/>
        <category label="Release" term="Release"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="Build Automation" term="Build Automation"/>
        <category label="psake" term="psake"/>
        <category label="Deployment" term="Deployment"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Introducing the psake Agent Skill]]></title>
        <id>https://psake.dev/blog/introducing-psake-agent-skill</id>
        <link href="https://psake.dev/blog/introducing-psake-agent-skill"/>
        <updated>2026-01-27T18:00:00.000Z</updated>
        <summary type="html"><![CDATA[Enhance your AI-assisted development with the new psake Agent Skill—bringing intelligent build automation guidance to Claude, GitHub Copilot, and other AI coding assistants.]]></summary>
        <content type="html"><![CDATA[<p>We're excited to announce the launch of the <a href="https://github.com/psake/psake-llm-tools" target="_blank" rel="noopener noreferrer">psake Agent Skill</a>—a specialized knowledge package that enables AI coding assistants like Claude and GitHub Copilot to provide expert assistance with psake build automation tasks. Built on the open <a href="https://agentskills.io/" target="_blank" rel="noopener noreferrer">Agent Skills</a> standard, this portable skill brings intelligent, context-aware guidance directly to your AI-assisted development workflow.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-psake-agent-skill">What is the psake Agent Skill?<a href="https://psake.dev/blog/introducing-psake-agent-skill#what-is-the-psake-agent-skill" class="hash-link" aria-label="Direct link to What is the psake Agent Skill?" title="Direct link to What is the psake Agent Skill?">​</a></h2>
<p>The psake Agent Skill is part of our growing collection of LLM tools designed to enhance how developers work with psake. Built on the open <a href="https://agentskills.io/" target="_blank" rel="noopener noreferrer">Agent Skills</a> standard, it provides AI assistants with deep knowledge of psake patterns, syntax, and best practices. This portable format means the same skill works across different AI platforms—whether you're using Claude, GitHub Copilot, or other compatible AI tools.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="key-features">Key Features<a href="https://psake.dev/blog/introducing-psake-agent-skill#key-features" class="hash-link" aria-label="Direct link to Key Features" title="Direct link to Key Features">​</a></h2>
<p>The skill includes four comprehensive knowledge components:</p>
<p><strong>SKILL.md</strong> – Core psake fundamentals covering command syntax, task definitions, dependencies, and troubleshooting patterns. This ensures your AI assistant understands the basics before diving into more complex scenarios.</p>
<p><strong>PowerShell Modules Reference</strong> – Detailed guidance on using PowerShellBuild for module development workflows, including task patterns, build configurations, and testing integration.</p>
<p><strong>Build Types Reference</strong> – Practical patterns for .NET, Node.js, and Docker builds, providing real-world examples for different project types.</p>
<p><strong>Advanced Reference</strong> – Coverage of sophisticated topics like dynamic task generation, custom logging implementations, and CI/CD pipeline integration.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-can-ai-assistants-do-with-this-skill">What Can AI Assistants Do With This Skill?<a href="https://psake.dev/blog/introducing-psake-agent-skill#what-can-ai-assistants-do-with-this-skill" class="hash-link" aria-label="Direct link to What Can AI Assistants Do With This Skill?" title="Direct link to What Can AI Assistants Do With This Skill?">​</a></h2>
<p>Once you've loaded the psake skill, your AI assistant can help with tasks like:</p>
<ul>
<li>Building complete psakefiles with integrated Pester testing frameworks</li>
<li>Establishing build configurations for .NET solutions and PowerShell modules</li>
<li>Implementing dynamic task generation from configuration files</li>
<li>Troubleshooting build failures and dependency issues</li>
<li>Integrating psake workflows into CI/CD pipelines</li>
<li>Creating custom logging mechanisms</li>
<li>Developing cross-platform build scripts</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="getting-started">Getting Started<a href="https://psake.dev/blog/introducing-psake-agent-skill#getting-started" class="hash-link" aria-label="Direct link to Getting Started" title="Direct link to Getting Started">​</a></h2>
<p>The psake Agent Skill works with multiple AI platforms thanks to the open Agent Skills standard.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-with-claude">Using with Claude<a href="https://psake.dev/blog/introducing-psake-agent-skill#using-with-claude" class="hash-link" aria-label="Direct link to Using with Claude" title="Direct link to Using with Claude">​</a></h3>
<ol>
<li>Visit the <a href="https://github.com/psake/psake-llm-tools" target="_blank" rel="noopener noreferrer">psake-llm-tools repository</a></li>
<li>Download the <code>psake.skill</code> file from the releases section</li>
<li>Upload it to Claude through the skills interface</li>
<li>Start building with AI-assisted psake expertise</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-with-github-copilot">Using with GitHub Copilot<a href="https://psake.dev/blog/introducing-psake-agent-skill#using-with-github-copilot" class="hash-link" aria-label="Direct link to Using with GitHub Copilot" title="Direct link to Using with GitHub Copilot">​</a></h3>
<ol>
<li>Download the <code>psake.skill</code> file from the <a href="https://github.com/psake/psake-llm-tools" target="_blank" rel="noopener noreferrer">repository</a></li>
<li>Follow the <a href="https://code.visualstudio.com/docs/copilot/customization/agent-skills#_use-shared-skills" target="_blank" rel="noopener noreferrer">VS Code instructions for using shared skills</a></li>
<li>Configure the skill in your workspace or user settings</li>
<li>Access psake expertise directly in your editor</li>
</ol>
<p>The same skill file works across both platforms, making it easy to maintain consistent AI assistance regardless of which tool you prefer.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="open-standard-open-source">Open Standard, Open Source<a href="https://psake.dev/blog/introducing-psake-agent-skill#open-standard-open-source" class="hash-link" aria-label="Direct link to Open Standard, Open Source" title="Direct link to Open Standard, Open Source">​</a></h2>
<p>By building on the <a href="https://agentskills.io/" target="_blank" rel="noopener noreferrer">Agent Skills</a> open standard, we ensure that psake expertise is portable across AI platforms. As more tools adopt this standard, your investment in configuring the psake skill will continue to pay dividends across your entire development toolchain.</p>
<p>The psake-llm-tools repository is open source and welcomes community contributions. If you have patterns, examples, or improvements that would benefit other developers using psake with AI assistants, we'd love to see your pull requests.</p>
<p>Whether you're new to psake or a seasoned automation expert, the psake Agent Skill can help streamline your workflow and provide intelligent guidance when you need it most. Give it a try and let us know what you think!</p>
<p>Check out the project at <a href="https://github.com/psake/psake-llm-tools" target="_blank" rel="noopener noreferrer">github.com/psake/psake-llm-tools</a>.</p>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
        <category label="Announcement" term="Announcement"/>
        <category label="psake" term="psake"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="Build Automation" term="Build Automation"/>
        <category label="CI/CD" term="CI/CD"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[New Releases & More!]]></title>
        <id>https://psake.dev/blog/new-releases-and-more</id>
        <link href="https://psake.dev/blog/new-releases-and-more"/>
        <updated>2025-08-03T23:38:05.100Z</updated>
        <summary type="html"><![CDATA[Discover the latest updates and releases in psake and PowerShellBuild that you won't want to miss!]]></summary>
        <content type="html"><![CDATA[<p>It's been a while since our last update, and we've got some exciting news to
share! In this post, we'll cover recent releases, welcome new team members, and
highlight the various initiatives we're working on to make psake even better.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="latest-versions">Latest Versions<a href="https://psake.dev/blog/new-releases-and-more#latest-versions" class="hash-link" aria-label="Direct link to Latest Versions" title="Direct link to Latest Versions">​</a></h2>
<p>Since launching this documentation site, we haven't been great about announcing
new versions here. You could say we've been in stealth mode (though we're
definitely not that cool).</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="psake">psake<a href="https://psake.dev/blog/new-releases-and-more#psake" class="hash-link" aria-label="Direct link to psake" title="Direct link to psake">​</a></h3>
<p>Back in October, we released psake 4.9.1, and since then we've merged several
pull requests, including some fantastic community contributions.</p>
<p>Check out the
<a href="https://github.com/psake/psake/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer">psake Changelog</a> for all
the details.</p>
<p>The next release will introduce a new way to override the psake logging
mechanism. This will allow teams to integrate additional logging frameworks or
create improved CI/CD-specific workflows.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="powershellbuild">PowerShellBuild<a href="https://psake.dev/blog/new-releases-and-more#powershellbuild" class="hash-link" aria-label="Direct link to PowerShellBuild" title="Direct link to PowerShellBuild">​</a></h3>
<p>Just a few days ago, we updated PowerShellBuild - our collection of common tasks
for psake and Invoke-Build - to support overriding task dependencies. We also
added localization support (more on that below). This brings us to version 0.7.3
as our latest release. Since version 0.6.2, we've seen 4.5k downloads, and we
hope to keep improving the project based on your feedback.</p>
<p>See the
<a href="https://github.com/psake/PowerShellBuild/blob/main/CHANGELOG.md" target="_blank" rel="noopener noreferrer">PowerShellBuild Changelog</a>
for complete details.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="welcome-our-newest-team-members">Welcome Our Newest Team Members<a href="https://psake.dev/blog/new-releases-and-more#welcome-our-newest-team-members" class="hash-link" aria-label="Direct link to Welcome Our Newest Team Members" title="Direct link to Welcome Our Newest Team Members">​</a></h2>
<p>You may have noticed them working on and reviewing code in our repositories, but
we'd like to formally welcome Joshua Hendricks and Trent Blackburn as new
members of the psake core team!</p>
<p><strong>Joshua</strong> is our resident
<a href="https://mvp.microsoft.com/MVP/profile/f98b4f3e-12fd-40de-bdce-1467f04d430d" target="_blank" rel="noopener noreferrer">MVP</a>
who's well-known for presenting at PowerShell + DevOps Global Summit on building
beautiful docs and sending notifications. He's a developer at Milestone Systems
where he maintains their PowerShell module.</p>
<p><strong>Trent</strong> currently develops PowerShell automations at Tesla, previously
specialized in PowerShell at Amazon, and has also presented at the annual
PowerShell + DevOps Global Summit.</p>
<p>Both bring incredible expertise to the team, and we're excited to have them
aboard! If you're interested in contributing to psake, please consider opening
an issue or submitting a pull request—we'd love to hear from you.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="expanding-global-accessibility-with-localization">Expanding Global Accessibility with Localization<a href="https://psake.dev/blog/new-releases-and-more#expanding-global-accessibility-with-localization" class="hash-link" aria-label="Direct link to Expanding Global Accessibility with Localization" title="Direct link to Expanding Global Accessibility with Localization">​</a></h2>
<p>psake has long had the framework in place for supporting localization (l10n),
but until now has only been available in English. One of our key goals is making
psake as accessible as possible for users worldwide.</p>
<p>To make community contributions easier, we've set up a
<a href="http://crowdin.com/project/psake" target="_blank" rel="noopener noreferrer">Crowdin project</a> that enables straightforward
translation requests and suggestions.</p>
<p>With the Crowdin project now live, we have a streamlined pipeline for
introducing new localized versions. We'd love your help in making psake
available in more languages - please consider contributing translations!</p>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
        <category label="Announcement" term="Announcement"/>
        <category label="Release" term="Release"/>
        <category label="psake" term="psake"/>
        <category label="PowerShell" term="PowerShell"/>
        <category label="Build Automation" term="Build Automation"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[First Blog Post]]></title>
        <id>https://psake.dev/blog/first-blog-post</id>
        <link href="https://psake.dev/blog/first-blog-post"/>
        <updated>2024-10-05T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[First blog post! I'll keep this short and sweet. This post is to announce that]]></summary>
        <content type="html"><![CDATA[<p>First blog post! I'll keep this short and sweet. This post is to announce that
deployment of <a href="https://psake.dev/" target="_blank" rel="noopener noreferrer">psake.dev</a>!</p>
<p>This first iteration is composed of the original docs on the psake repository.
I'll be slowly reviewing all the docs and updating them to make it easier for
folks to get started.</p>
<p>In the near future, I'll be looking at more common CI/CD workflows and making
sure we have good examples. Have suggestions? PR's are welcome!</p>]]></content>
        <author>
            <name>Gilbert Sanchez</name>
            <uri>https://gilbertsanchez.com</uri>
        </author>
    </entry>
</feed>