Why package management is a delivery problem
Package feeds look like plumbing until they fail. A public registry has an outage and every build in the company stops. A developer publishes an internal library from a laptop and nobody can reproduce it. A package is pulled from a typo-squatted name. A prerelease build ends up in production because nothing separated “tested” from “experimental”.
Azure Artifacts solves these problems if configured with intent. This page explains how we set it up as part of our Azure DevOps consulting, alongside the pipelines described in our multi-stage YAML design page.
What good looks like
- Internal libraries are published by CI only, with versions that mean something.
- Builds resolve dependencies through a feed, not directly from the internet.
- Consumers can choose stable or prerelease versions through views.
- Authentication uses build identities and managed credentials, never a shared personal token.
- Old versions are cleaned up by policy so storage and confusion stay under control.
How it works in practice
Feeds and scope
A feed can be scoped to the organisation or to a project. Organisation feeds suit shared libraries consumed by many projects. Project feeds suit packages that belong to one product. Most teams do well with a small number of feeds: one for shared internal packages and perhaps one per major product. More feeds multiply permission management without much benefit.
Upstream sources
Enabling upstream sources lets a feed fetch from npmjs, NuGet.org, Maven Central and others, and keep a copy of what was used. We recommend consuming public packages through the feed in all builds. It gives you protection against registry outages and against removed or yanked packages, and it makes it clear which public dependencies you actually rely on. Combine this with dependency update tooling and vulnerability scanning so the cache does not become a place where old risk accumulates.
Views and promotion
Packages publish to the feed’s local view. You can then promote them to a Prerelease view and later a Release view. Consumers who want stable packages point at the release view, while test environments can use prerelease. Promotion happens from a pipeline stage after tests pass, which pairs naturally with deployment environments and approval gates.
Pipeline and developer authentication
For npm, a project-level .npmrc points at the feed, and the pipeline authenticates with a task:
steps:
- task: NodeTool@0
inputs:
versionSpec: "20.x"
- task: npmAuthenticate@0
inputs:
workingFile: .npmrc
- script: npm ci
displayName: Install dependencies
- script: npm publish
displayName: Publish package
workingDirectory: packages/ui
NuGet uses NuGetAuthenticate@1 with a nuget.config listing the feed, and Maven uses MavenAuthenticate@0 with a repository entry in pom.xml and settings. The build identity, usually the project’s build service account, needs at least the Contributor role on the feed to publish. Developers authenticate from their machines using the credential provider for their tool, which avoids pasting tokens into configuration files.
Versioning and retention
Packages need predictable versions. We use semantic versioning, with the pipeline computing prerelease suffixes for non-main branches, for instance a build number appended on feature branches. Retention policies on the feed keep a defined number of recent versions and protect those promoted to release views, so storage does not grow unchecked.
Docker images and Azure Container Registry
Azure Artifacts does not host container images. For Docker we use Azure Container Registry, with pipelines authenticating through a service connection, repository naming conventions, tag policies and cleanup rules. Our AKS deployment integration page covers how images then reach clusters. For container build practice more broadly, see our Docker containerisation service.
Security of the software supply chain
A package feed is a trust boundary. A malicious or compromised dependency can run code on every developer machine and build agent. We reduce the risk in layers. Builds resolve through a feed with upstream sources, so there is one controlled path. Package names are scoped to your organisation for internal packages, which reduces the chance of a public package with the same name being installed by mistake (a dependency confusion attack). Lock files are committed, and installs in CI use the strict mode such as npm ci, so builds fail rather than silently pick up different versions.
Visibility into what you depend on
Upstream caching gives you a list of public packages in use, which becomes the starting point for vulnerability reporting and licence checks. We pair the feed with an automated dependency update tool and a scanner in the pipeline, so known-vulnerable versions raise a pull request or a failed build rather than a surprise.
Migrating existing packages
If packages currently live on a file share, a laptop or another registry, we publish them into the feed with their existing versions, update consumers to the new source, and then retire the old location. Doing this in stages, one package family at a time, avoids a big-bang cutover.
Decisions and trade-offs
Azure Artifacts or GitHub Packages? If your code and pipelines are in Azure DevOps, Artifacts keeps everything together. If you are moving to GitHub, see our page on Azure DevOps to GitHub migration planning before moving packages.
Organisation or project scope? Organisation scope is convenient but wide. If package access must follow project permissions, use project scope.
Upstreams on or off? On is the safer default. Off may suit regulated environments that want only vetted packages, but then you need a process for approving new ones.
When not to buy this. If you publish nothing internal and builds are healthy against public registries, you may not need a feed yet. Add one when outages, compliance or shared libraries create a reason.
Common failure modes
- Build identity lacks permission. Publishing fails with a 403. We grant the right role up front.
- Floating versions. Consumers using latest get surprises. We pin ranges deliberately.
- Personal access tokens in
.npmrc. They expire and leak. Credential providers and tasks replace them. - No cleanup. Thousands of prerelease versions bury the useful ones.
Delivery and handover
You receive configured feeds, upstreams, views, permissions, example pipeline snippets for each package type, Azure Container Registry if needed, and documentation for developers. We test by publishing and consuming a real package end to end before handover.
How to tell it is working
Builds no longer depend on public registry uptime, internal libraries have traceable versions, a developer can onboard in minutes without asking for a token, and prerelease packages never reach production by accident. If you want your package flow reviewed, get in touch.