<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-AU">
  <id>https://david.gardiner.net.au/tags/Package%20Management.xml</id>
  <title type="html">David Gardiner - Package Management</title>
  <updated>2026-04-15T00:26:29.611Z</updated>
  <subtitle>Blog posts tagged with &apos;Package Management&apos; - A blog of software development, .NET and other interesting things</subtitle>
  <rights>Copyright 2026 David Gardiner</rights>
  <icon>https://www.gravatar.com/avatar/37edf2567185071646d62ba28b868fab?s=64</icon>
  <logo>https://www.gravatar.com/avatar/37edf2567185071646d62ba28b868fab?s=256</logo>
  <generator uri="https://github.com/flcdrg/astrojs-atom" version="3">astrojs-atom</generator>
  <author>
    <name>David Gardiner</name>
  </author>
  <link href="https://david.gardiner.net.au/tags/Package%20Management.xml" rel="self" type="application/atom+xml"/>
  <link href="https://david.gardiner.net.au/tags/Package%20Management" rel="alternate" type="text/html" hreflang="en-AU"/>
  <category term="Package Management"/>
  <category term="Software Development"/>
  <entry>
    <id>https://david.gardiner.net.au/2020/04/4-into-3-part-2</id>
    <updated>2020-04-26T21:30:00.000+09:30</updated>
    <title>4 doesn&apos;t go into 3 part 2</title>
    <link href="https://david.gardiner.net.au/2020/04/4-into-3-part-2" rel="alternate" type="text/html" title="4 doesn&apos;t go into 3 part 2"/>
    <category term="Azure Artifacts"/>
    <category term="Azure Pipelines"/>
    <category term="Package Management"/>
    <category term="Versioning"/>
    <published>2020-04-26T21:30:00.000+09:30</published>
    <summary type="html">Last time, we&apos;d figured out a strategy for getting our data up into Azure Artifacts. The problem was that we are using SemVer pre-release notation, and the Azure Artifacts command line and Azure Pipelines task don&apos;t support querying pre-release versions using wildcards. The CLI tools and Pipelines task will work if we know the exact pre-release version required, but how to find that out? The Azure DevOps Services REST API.</summary>
    <content type="html">
&lt;p&gt;&lt;a href=&quot;/2020/04/4-into-3&quot;&gt;Last time&lt;/a&gt;, we&apos;d figured out a strategy for getting our data up into Azure Artifacts. The problem was that we are using SemVer pre-release notation, and the Azure Artifacts command line and Azure Pipelines task don&apos;t support querying pre-release versions using wildcards.&lt;/p&gt;
&lt;p&gt;The CLI tools and Pipelines task will work if we know the exact pre-release version required, but how to find that out? The Azure DevOps Services REST API.&lt;/p&gt;
&lt;p&gt;Here&apos;s an example PowerShell script you could use to find out the latest version of a package named &apos;mypackage&apos;. It sets a pipeline variable that can be used in subsequent Azure Pipeline tasks.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$url = &quot;https://feeds.dev.azure.com/{organization}/{project}/_apis/packaging/Feeds/{feedId}/packages?api-version=5.1-preview.1&amp;amp;packageNameQuery=mypackage&quot;

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes((&quot;{0}:{1}&quot; -f &quot;&quot;,$env:SYSTEM_ACCESSTOKEN)))
$result = Invoke-RestMethod -Uri $url -Method Get -ContentType &quot;application/json&quot; -Headers @{Authorization=(&quot;Basic {0}&quot; -f $base64AuthInfo)}

$packageVersion = $result.value.versions.normalizedVersion
Write-Host &quot;##vso[task.setvariable variable=packageVersion]$packageVersion&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&apos;re making use of the &lt;code&gt;packageNameQuery&lt;/code&gt; parameter to filter by the package name, but there are other filtering options available. You could also do more filtering on the JSON data that the REST API returns.&lt;/p&gt;
&lt;p&gt;Now we can use the &lt;a href=&quot;https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/universal-packages-v0?view=azure-pipelines&amp;amp;viewFallbackFrom=azure-devops&quot;&gt;Universal Package task&lt;/a&gt;, requesting the specific version. eg.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Download Universal Package
steps:
- task: UniversalPackages@0
  displayName: &apos;Universal download&apos;
  inputs:
    downloadDirectory: Application
    vstsFeed: &apos;00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000001&apos;
    vstsFeedPackage: imagemagick
    vstsPackageVersion: &apos;$(packageVersion)&apos;
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <id>https://david.gardiner.net.au/2020/04/4-into-3</id>
    <updated>2020-04-25T12:00:00.000+09:30</updated>
    <title>4 doesn&apos;t go into 3</title>
    <link href="https://david.gardiner.net.au/2020/04/4-into-3" rel="alternate" type="text/html" title="4 doesn&apos;t go into 3"/>
    <category term="Azure Artifacts"/>
    <category term="Azure Pipelines"/>
    <category term="Package Management"/>
    <category term="Versioning"/>
    <published>2020-04-25T12:00:00.000+09:30</published>
    <summary type="html">There&apos;s different ways of versioning things. Windows has had a 4-part version scheme that is used by itself and most Windows applications. The convention is &amp;lt;major version&amp;gt;.&amp;lt;minor version&amp;gt;.&amp;lt;build number&amp;gt;.&amp;lt;revision&amp;gt;. .NET supports this through classes like AssemblyVersionAttribute and Version. SemVer is a 3-part scheme (MAJOR.MINOR.PATCH) with optional pre-release or metadata that has seen wide industry adoption, especially by package management tools (npm, NuGet etc). …</summary>
    <content type="html">&lt;p&gt;There&apos;s different ways of versioning things. Windows has had a &lt;a href=&quot;https://learn.microsoft.com/windows/win32/menurc/versioninfo-resource&quot;&gt;4-part version scheme&lt;/a&gt; that is used by itself and most Windows applications. The convention is &lt;code&gt;&amp;lt;major version&amp;gt;.&amp;lt;minor version&amp;gt;.&amp;lt;build number&amp;gt;.&amp;lt;revision&amp;gt;&lt;/code&gt;. .NET supports this through classes like &lt;a href=&quot;https://learn.microsoft.com/dotnet/api/system.reflection.assemblyversionattribute?view=net-10.0&quot;&gt;&lt;code&gt;AssemblyVersionAttribute&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://learn.microsoft.com/dotnet/api/system.version?view=net-10.0&quot;&gt;&lt;code&gt;Version&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://semver.org/&quot;&gt;SemVer&lt;/a&gt; is a 3-part scheme (&lt;code&gt;MAJOR.MINOR.PATCH&lt;/code&gt;) with optional pre-release or metadata that has seen wide industry adoption, especially by package management tools (npm, NuGet etc).&lt;/p&gt;
&lt;p&gt;Using SemVer-versioned components in an ecosystem that uses 4-part versioning is pretty straight forward. Just tack an extra &quot;.0&quot; on the end if it really wants to see 4 parts.&lt;/p&gt;
&lt;p&gt;On the other hand, using 4-part versions in a SemVer ecosystem is hard. You can&apos;t just drop one of the parts unless you know with certainty that it will never, ever be significant.&lt;/p&gt;
&lt;p&gt;And that&apos;s the problem. How do you preserve information from 4 things when you&apos;ve only got 3 places to put it?&lt;/p&gt;
&lt;p&gt;I hit this problem recently when looking to push some versioned data that&apos;s generated on-prem up to an Azure Pipeline so it could be used in the build process. I decided that &lt;a href=&quot;https://learn.microsoft.com/azure/devops/artifacts/start-using-azure-artifacts?view=azure-devops&quot;&gt;Azure Artifacts&lt;/a&gt; would be a good way to get the data safely into a place where the Pipeline could access it.&lt;/p&gt;
&lt;p&gt;Azure Artifacts has built-in support for a number of package formats (NuGet, npm, Maven and others), but this data wasn&apos;t any of those, so the &apos;&lt;a href=&quot;https://learn.microsoft.com/azure/devops/artifacts/quickstarts/universal-packages?view=azure-devops&amp;amp;tabs=azuredevops&quot;&gt;Universal Package&lt;/a&gt;&apos; type seemed most appropriate. But as I was about to discover, Universal Packages are versioned with SemVer 2 (and no metadata allowed).&lt;/p&gt;
&lt;p&gt;As the third part of the 4-part version number was zero, I was thinking I could just drop that to convert to a 3-part version number. But after some investigation it turns out that assumption was wrong - the third part can change.&lt;/p&gt;
&lt;p&gt;I&apos;m not the first to &lt;a href=&quot;https://developercommunity.visualstudio.com/idea/442168/universal-packages-need-to-support-four-version-nu.html&quot;&gt;encounter this problem&lt;/a&gt;, and the final comment on that article by &lt;a href=&quot;https://web.archive.org/web/20240520062358/http://mitchdenny.com/&quot;&gt;Mitch Denny&lt;/a&gt; (an Australian developer who I&apos;m honoured to know, and who was the Program Manager for Azure Artifacts at the time) gives an interesting workaround.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;1.2.3.4&lt;/code&gt; could be encoded in SemVer as &lt;code&gt;1.2.3-4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I&apos;m more used to seeing the pre-release with text (eg. 1.2.3-beta.4), but reviewing the SemVer site (point 9), they actually give &lt;code&gt;1.0.0-0.3.7&lt;/code&gt; as an example, so this should be ok. It is technically a &apos;pre-release&apos; version, but it has preserved all the data.&lt;/p&gt;
&lt;p&gt;There&apos;s one final gotcha, and it relates to the version being pre-release.&lt;/p&gt;
&lt;p&gt;I mentioned earlier that I was going to use the Universal Package in an Azure Pipeline. To download the package in the pipeline, you use the &lt;a href=&quot;https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/universal-packages-v0?view=azure-pipelines&amp;amp;viewFallbackFrom=azure-devops&quot;&gt;Universal Package&lt;/a&gt; task.&lt;/p&gt;
&lt;p&gt;The problem is that this task, like the CLI tooling doesn&apos;t support pre-release versions using wildcards. This is explicitly called out in the documentation for the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/devops/artifacts/quickstarts/universal-packages?view=azure-devops&amp;amp;tabs=azuredevops#downloading-the-latest-version&quot;&gt;Universal Packages Quickstart&lt;/a&gt; &quot;Wildcard expressions do not currently support pre-release versions. It is not possible to get the latest pre-release version of a package.&quot;&lt;/p&gt;
&lt;p&gt;Next steps, see if using I can use the &lt;a href=&quot;https://learn.microsoft.com/rest/api/azure/devops/artifacts/artifact-details?view=azure-devops-rest-5.0&quot;&gt;REST API&lt;/a&gt; to obtain the version and pass that to the Pipelines task.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/2020/04/4-into-3-part-2&quot;&gt;Continued in part 2&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
</feed>
