DevOpsClicks
โ† Home
๐Ÿ”ต Complete CI/CD Platform Reference

Azure DevOps Complete Guide

End-to-end DevOps platform โ€” Classic Editor, YAML Pipelines, User Management, Permissions, Artifacts, and production release patterns.

15
Chapters
30+
Pipelines
100%
Free
01๐Ÿ”ต

Introduction to Azure DevOps

One Platform for Everything

Azure DevOps is like a Swiss Army knife for software teams โ€” it has Git repos, project boards, CI/CD pipelines, artifact storage, and test management all in one place. Unlike Jenkins (which only does CI/CD), Azure DevOps handles the entire software lifecycle from planning to deployment.
The 5 Services โ€” Think of Them as 5 Rooms
๐Ÿ“‚
Azure Repos
Your code lives here. Git repositories with pull requests, branch protection, and code review. Like GitHub but integrated into Azure DevOps.
๐Ÿ“‹
Azure Boards
Track work: user stories, bugs, tasks. Kanban boards, sprint planning, backlogs. Like Jira but built into the same platform.
โš™๏ธ
Azure Pipelines
Automate builds and deployments. Classic Editor (UI) or YAML (code). This is the CI/CD engine โ€” the heart of DevOps.
๐Ÿ“ฆ
Azure Artifacts
Store private packages โ€” NPM, Maven, NuGet, Python. Like a private Nexus or JFrog inside Azure DevOps.
๐Ÿงช
Azure Test Plans
Manual and automated testing. Link test cases to user stories. Track test coverage.
FeatureAzure DevOpsGitHub ActionsJenkins
HostingCloud + On-prem (Server)Cloud onlySelf-hosted only
PipelineYAML + Classic UIYAML onlyGroovy (Jenkinsfile)
Project BoardsBuilt-in (Boards)GitHub IssuesNone (use Jira)
Artifact RegistryBuilt-in (Artifacts)GitHub PackagesExternal (Nexus)
Best ForEnterprise + Azure + .NETOpen source + GitHubFull control + plugins
02๐Ÿข

Organization & Project Setup

Structure Your Azure DevOps

Azure DevOps has a hierarchy: Organization โ†’ Project โ†’ Repos/Pipelines/Boards. Think of Organization as your company, Projects as departments, and Repos as individual applications.
Hierarchy Explained
๐Ÿข
Organization
Top level โ€” your company name. Users, billing, and policies live here. URL: dev.azure.com/yourcompany
๐Ÿ“‚
Project
A workspace for a team or product. Has its own repos, boards, and pipelines. Example: "E-Commerce Platform" or "Mobile App"
๐Ÿ“
Repository
One Git repo inside a project. A project can have multiple repos. Example: order-service, user-service, frontend
Creating Your First Project
โœ“Go to dev.azure.com โ†’ Sign in with Microsoft account
โœ“Create Organization (your company name)
โœ“Click "New Project" โ†’ Name: "my-first-project"
โœ“Choose visibility: Private (default) or Public
โœ“Version Control: Git (always Git, never TFVC for new projects)
โœ“Work Item Process: Agile (recommended) or Scrum or Basic
โœ“Click Create โ†’ Your project is ready!
๐Ÿ’ก Free Tier

Azure DevOps is FREE for up to 5 users with unlimited private repos and 1800 minutes/month of pipeline time. More than enough for small teams and learning.

03๐Ÿ“‚

Azure Repos & Branch Policies

Code Management Done Right

Azure Repos hosts your Git repositories. The killer feature is Branch Policies โ€” rules that prevent bad code from reaching your main branch. No one can push directly to main. Every change must go through a pull request with reviews and passing builds.
Branch Policies โ€” Non-Negotiable for Production
โœ“Require pull request to merge โ€” NO direct push to main allowed
โœ“Minimum reviewers: 2 approvals required (at least 1 must be from code owners)
โœ“Build validation: CI pipeline MUST pass before merge is allowed
โœ“Linked work item: every PR must reference a user story or bug (traceability)
โœ“Comment resolution: ALL code review comments must be resolved
โœ“Reset votes on push: if developer pushes new commits, previous approvals are reset
โœ“Squash merge: clean single-commit history on main branch
Pull Request Workflow
WORKFLOW# 1. Developer creates feature branch git checkout -b feature/payment-gateway # 2. Developer makes changes and pushes git add . && git commit -m "feat: add Razorpay integration" git push origin feature/payment-gateway # 3. Azure DevOps auto-creates Pull Request link # 4. CI pipeline runs automatically on the PR # 5. 2 reviewers review the code and approve # 6. All checks pass โ†’ Merge button becomes available # 7. Squash merge into main โ†’ clean history # 8. Feature branch auto-deleted
04๐Ÿ“‹

Azure Boards

Track Work Like a Pro

Boards is the project management tool โ€” think of it as Jira built into Azure DevOps. You create user stories, break them into tasks, track them on Kanban boards, and link them to commits and pull requests for full traceability.
Work Item Types
TypePurposeExample
EpicLarge business initiative (months)Launch Payment Module
FeatureDeliverable functionality (weeks)Razorpay Integration
User StoryUser-facing requirementAs a user, I want to pay via UPI
TaskTechnical work (hours/days)Create Razorpay API wrapper
BugDefect to fixPayment fails for amounts > 10000
๐Ÿ’ก Auto-Linking

Include work item ID in commits or PR titles: "feat: add UPI flow #1234" โ€” Azure DevOps automatically links the commit to work item #1234. In Boards, you can see which commits and PRs relate to each story. Full traceability from requirement to deployment.

05๐Ÿ–ฑ๏ธ

Classic Editor Pipelines

UI-Based Build & Release โ€” No YAML Needed

Classic Editor lets you build CI/CD pipelines by clicking buttons and filling forms in the web UI โ€” no YAML knowledge needed. It is great for beginners and simple pipelines, but YAML is recommended for production because it is version-controlled.
Creating a Classic Build Pipeline
โœ“Go to Pipelines โ†’ New Pipeline โ†’ Click "Use the classic editor" link at bottom
โœ“Select source: Azure Repos Git โ†’ Pick your repository and branch
โœ“Choose template: ".NET Core" or "Maven" or "Node.js" or start with "Empty Job"
โœ“Agent Pool: Azure Pipelines (Microsoft-hosted) or your self-hosted pool
โœ“Add tasks by clicking the + button: Get Sources โ†’ Build โ†’ Test โ†’ Publish
โœ“Configure triggers: Enable "Continuous Integration" checkbox โ†’ builds on every push
โœ“Save & Queue โ†’ Your first build runs!
Classic vs YAML โ€” Honest Comparison
Classic EditorYAML Pipeline
Click buttons to configureWrite YAML code
Stored in Azure DevOps (not in Git!)Stored in Git repo as azure-pipelines.yml
Cannot be code-reviewed in PRCan be reviewed in pull requests
Easy to start, hard to maintainHarder to start, easy to maintain
No version historyFull Git history for pipeline changes
Good for learning and demosRequired for production
Limited to available UI optionsFull flexibility with scripts and conditions
Classic Release Pipeline (CD)
Classic Release pipelines are a separate concept โ€” they take the output (artifact) from a Build pipeline and deploy it across environments. They have a visual stage editor that is very intuitive.
โœ“Go to Pipelines โ†’ Releases โ†’ New Release Pipeline
โœ“Select template: "Azure App Service deployment" or "Empty job"
โœ“Add Artifact: Select your Build pipeline as source
โœ“Add Stages: Dev โ†’ Staging โ†’ Production
โœ“Each stage has: Pre-deployment conditions (approvals), Tasks (deployment steps), Post-deployment gates
โœ“Configure Approvals: Click the lightning bolt icon โ†’ Add approvers for Staging and Production
โœ“Enable Continuous Deployment trigger: auto-deploys when new build artifact is ready
โš ๏ธ Classic Releases are Legacy

Microsoft is pushing teams toward YAML-based multi-stage pipelines. Classic Releases still work and are supported, but new features are only added to YAML. Learn YAML for long-term career growth.

06๐Ÿ“

YAML Pipeline Basics

Pipeline as Code โ€” The Modern Way

YAML pipelines live in your Git repository as a file called azure-pipelines.yml. Every change to the pipeline is tracked in Git, can be code-reviewed, and is fully reproducible. This is the recommended approach for all new projects.
Complete YAML Pipeline โ€” Line by Line
AZURE-PIPELINES.YML# azure-pipelines.yml โ€” stored in your Git repo root trigger: # WHEN does it run? branches: include: - main # Run on push to main - release/* # Run on push to release branches exclude: - feature/experimental # Skip this branch pool: # WHERE does it run? vmImage: 'ubuntu-latest' # Microsoft-hosted Ubuntu agent variables: # WHAT values do we need? buildConfiguration: 'Release' appName: 'order-service' stages: - stage: Build # STAGE 1: Build displayName: 'Build & Test' jobs: - job: BuildJob displayName: 'Build the application' steps: - script: echo "Building $(appName)" # Use variable with $() displayName: 'Print app name' - script: mvn clean package -DskipTests=false displayName: 'Maven Build & Test' - task: PublishBuildArtifacts@1 # Save output for deploy stage inputs: PathtoPublish: 'target/app.jar' ArtifactName: 'drop' - stage: Deploy # STAGE 2: Deploy displayName: 'Deploy to Staging' dependsOn: Build # Only runs if Build succeeds jobs: - deployment: DeployWeb # Special deployment job environment: 'staging' # Links to environment (approvals here) strategy: runOnce: deploy: steps: - download: current # Download artifact from Build stage artifact: drop - script: echo 'Deploying to staging...'
Pipeline Hierarchy โ€” Simple
LevelContainsThink of it as...
PipelineStagesThe whole recipe
StageJobsA chapter (Build, Test, Deploy)
JobStepsA section within the chapter
StepTask or ScriptOne instruction (run this command)
07๐Ÿš€

YAML Advanced Features

Variables, Conditions, Environments & Approvals

Master these features to build production-grade pipelines โ€” variable groups linked to Key Vault, conditional stages, environment approvals, and deployment strategies.
Variable Groups & Key Vault Integration
YAMLvariables: # Inline variable - name: appName value: 'order-service' # Variable Group (shared across pipelines) - group: 'production-secrets' # Contains: DB_PASSWORD, API_KEY, etc. # Linked to Azure Key Vault โ†’ secrets auto-rotate! # Conditional variable - name: isProduction value: $[eq(variables['Build.SourceBranchName'], 'main')]
Conditions โ€” Control Which Stages Run
YAMLstages: - stage: DeployStaging displayName: 'Deploy to Staging' condition: | and( succeeded(), eq(variables['Build.SourceBranchName'], 'develop') ) - stage: DeployProduction displayName: 'Deploy to Production' condition: | and( succeeded(), eq(variables['Build.SourceBranchName'], 'main') ) jobs: - deployment: DeployProd environment: 'production' # Approval gate configured here! strategy: runOnce: deploy: steps: - script: echo 'Deploying to production!'
Environments & Approvals
๐ŸŸข
Development
No approvals. Auto-deploys on every push to develop. Fast feedback.
๐ŸŸก
Staging
1 approver. Deploys from release/* branches. QA team tests here.
๐Ÿ”ด
Production
2 approvers (lead + manager). Only from main. Deployment window: Mon-Thu, 10AM-4PM. No Friday deploys!
โœ“Create environment: Pipelines โ†’ Environments โ†’ New โ†’ "production"
โœ“Add approval: Click production โ†’ Approvals and checks โ†’ Add approvals
โœ“Add users who can approve (e.g., lead-devops, engineering-manager)
โœ“Optional: Add deployment window (business hours only)
โœ“Optional: Add branch control (only main branch can deploy here)
โœ“When pipeline reaches this environment, it PAUSES and waits for approval
08๐Ÿ”จ

CI Pipeline Examples

Build Pipelines for Every Stack

Complete CI pipeline examples for the most common technology stacks used in Indian and global enterprises.
.NET / C# Application
YAMLtrigger: [main] pool: { vmImage: 'ubuntu-latest' } steps: - task: UseDotNet@2 inputs: { version: '8.x' } - script: dotnet restore - script: dotnet build --configuration Release - script: dotnet test --collect:"XPlat Code Coverage" - task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: Cobertura summaryFileLocation: '**/coverage.cobertura.xml'
Java Spring Boot with Maven
YAMLtrigger: [main] pool: { vmImage: 'ubuntu-latest' } steps: - task: Maven@4 inputs: mavenPomFile: 'pom.xml' goals: 'clean package' publishJUnitResults: true testResultsFiles: '**/TEST-*.xml' - task: Docker@2 inputs: containerRegistry: 'acr-service-connection' repository: 'order-service' command: 'buildAndPush' tags: '$(Build.BuildId)'
Node.js / React Frontend
YAMLtrigger: [main] pool: { vmImage: 'ubuntu-latest' } steps: - task: NodeTool@0 inputs: { versionSpec: '20.x' } - script: npm ci - script: npm run lint - script: npm test -- --coverage --watchAll=false - script: npm run build - task: PublishBuildArtifacts@1 inputs: PathtoPublish: 'build' ArtifactName: 'frontend'
09๐Ÿš€

CD & Multi-Stage Releases

Build โ†’ Staging โ†’ Production in One File

Multi-stage YAML pipelines combine build AND deployment in one file. The artifact flows from Build โ†’ Staging โ†’ Production with approval gates between stages.
Complete Multi-Stage Pipeline
YAMLtrigger: [main] stages: - stage: Build jobs: - job: BuildAndTest pool: { vmImage: 'ubuntu-latest' } steps: - script: mvn clean package - publish: target/app.jar artifact: drop - stage: Staging dependsOn: Build jobs: - deployment: DeployStaging environment: 'staging' pool: { vmImage: 'ubuntu-latest' } strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureWebApp@1 inputs: azureSubscription: 'azure-connection' appType: 'webAppLinux' appName: 'myapp-staging' package: '$(Pipeline.Workspace)/drop/app.jar' - stage: Production dependsOn: Staging jobs: - deployment: DeployProd environment: 'production' # Requires manual approval! pool: { vmImage: 'ubuntu-latest' } strategy: runOnce: deploy: steps: - download: current artifact: drop - task: AzureWebApp@1 inputs: azureSubscription: 'azure-connection' appType: 'webAppLinux' appName: 'myapp-production' package: '$(Pipeline.Workspace)/drop/app.jar'
Deploy to Kubernetes (AKS)
YAML- stage: DeployAKS jobs: - deployment: DeployToAKS environment: 'aks-production' strategy: runOnce: deploy: steps: - task: KubernetesManifest@1 inputs: action: 'deploy' kubernetesServiceConnection: 'aks-prod' namespace: 'production' manifests: 'k8s/*.yaml' containers: 'myacr.azurecr.io/api:$(Build.BuildId)'
10๐Ÿ“‹

Templates & Reusability

DRY Pipelines Across 50 Microservices

Templates let you write pipeline logic once and reuse it across all your microservices. Instead of copy-pasting the same Docker+K8s pipeline into 50 repos, you call a template. Change once, all 50 pipelines update.
Step Template โ€” Reusable Steps
TEMPLATE# templates/docker-build.yml (in a shared repo) parameters: - name: imageName type: string - name: registry type: string default: 'myacr.azurecr.io' steps: - task: Docker@2 displayName: 'Build and Push Docker Image' inputs: containerRegistry: '${{ parameters.registry }}' repository: '${{ parameters.imageName }}' command: 'buildAndPush' tags: '$(Build.BuildId)'
Using the Template
YAML# azure-pipelines.yml (in each microservice repo) resources: repositories: - repository: templates type: git name: DevOps/pipeline-templates # Shared template repo stages: - stage: Build jobs: - job: Build steps: - script: mvn clean package - template: templates/docker-build.yml@templates parameters: imageName: 'order-service'
Extends Template โ€” Enterprise Governance
YAML# extends wraps the ENTIRE pipeline โ€” teams can only fill parameters # They CANNOT skip security scans or remove approval gates # azure-pipelines.yml (team's file โ€” very simple) resources: repositories: - repository: templates type: git name: DevOps/pipeline-templates extends: template: enterprise-pipeline.yml@templates parameters: appName: 'order-service' buildTool: 'maven' deployTo: 'aks-production'
๐Ÿ’ก template vs extends

template inserts reusable steps โ€” teams can add more. extends wraps the entire pipeline โ€” teams ONLY fill in parameters, they cannot skip mandatory steps. Use extends when security scans and approvals are mandatory company-wide.

11๐Ÿ“ฆ

Azure Artifacts

Private Package Registry

Artifacts hosts private package feeds. Your CI pipeline publishes packages (NPM, Maven, NuGet), and other pipelines or developers consume them. Like having a private npm registry or Nexus inside Azure DevOps.
az artifacts feed create --name company-packagesCreate a new feed
az artifacts universal publish --feed company-packages --name mylib --version 1.0.0 --path ./distPublish a package
NPM Private Feed
YAML# .npmrc โ€” point npm to your private feed registry=https://pkgs.dev.azure.com/myorg/MyProject/_packaging/company-packages/npm/registry/ always-auth=true # Pipeline step: publish to feed - task: Npm@1 inputs: command: 'publish' publishRegistry: 'useFeed' publishFeed: 'MyProject/company-packages'
12๐Ÿ‘ฅ

User Management & Permissions

Control Access at Every Level

Azure DevOps has a layered permission system: Organization โ†’ Project โ†’ Repository โ†’ Pipeline โ†’ Environment. You can control who can see, edit, build, and deploy at every level. This is critical for enterprise security.
Organization-Level Settings
โœ“Organization Settings โ†’ Users โ†’ Add users (via email or Azure AD)
โœ“Assign Access Level: Basic (full features), Stakeholder (free, limited features), or Visual Studio Subscriber
โœ“Connect Azure Active Directory for SSO โ€” users log in with company Microsoft accounts
โœ“Enable Conditional Access policies (MFA, approved devices only)
Project-Level Permissions
GroupPermissionsWho Goes Here
Project AdministratorsFull control over projectTech leads, DevOps leads
ContributorsEdit code, create pipelines, manage boardsDevelopers, DevOps engineers
ReadersView-only accessManagers, stakeholders, interns
Build AdministratorsManage pipelines and agentsCI/CD team
Release AdministratorsManage release pipelines and environmentsDevOps/SRE team
Repository-Level Permissions
PERMISSIONS# For each Git repository, you can set: # - Who can push to specific branches # - Who can create branches # - Who can force push (should be nobody!) # - Who can bypass branch policies (emergency only) # Example: Protect main branch # Project Settings โ†’ Repos โ†’ Select repo โ†’ Security # Deny: Force Push to main โ†’ Deny for ALL groups # Allow: Contribute to main โ†’ Only via pull requests # Allow: Bypass policies โ†’ Only "Emergency Admins" group
Personal Access Tokens (PATs)
PATs are like passwords for automation and CLI access. They have scoped permissions and expiration dates.
โœ“User Settings โ†’ Personal Access Tokens โ†’ New Token
โœ“Set scope: only grant minimum permissions needed (e.g., Code: Read)
โœ“Set expiration: 90 days max for security
โœ“Use PAT in Git clone: git clone https://pat@dev.azure.com/org/project/_git/repo
โœ“Use PAT in pipeline service connections for cross-project access
โœ“NEVER share PATs โ€” each user should have their own
โœ“Rotate PATs every 90 days
Environment Approvals (Deployment Permissions)
๐ŸŸข
Dev Environment
No approvals. Any contributor can trigger deploy.
๐ŸŸก
Staging
1 approver from QA team. Branch filter: release/* only.
๐Ÿ”ด
Production
2 approvers: tech lead + manager. Branch: main only. Business hours only. Exclusive lock (1 deploy at a time).
โš ๏ธ Least Privilege

Give everyone the MINIMUM permissions they need. Developers don't need admin access. Interns should be Readers. Only the DevOps lead should be able to modify production environment approvals.

13๐Ÿ”—

Service Connections

Connect to External Services

Service connections authenticate your pipelines to external services โ€” Azure subscriptions, Docker registries, Kubernetes clusters, AWS, SSH servers. They are centrally managed and scoped to specific pipelines.
TypeConnects ToBest Auth Method
Azure Resource ManagerAzure subscriptionManaged Identity (no passwords!) or Service Principal
Docker RegistryACR, Docker Hub, ECRService Principal for ACR, username/password for others
KubernetesAKS, EKS, GKEKubeconfig or Azure subscription (for AKS)
SSHRemote Linux serversSSH key pair
GitHubGitHub repositoriesGitHub App or PAT
GenericAny REST APIBearer token or basic auth
โœ“Create: Project Settings โ†’ Service Connections โ†’ New
โœ“Scope: Grant to specific pipelines only (not all pipelines)
โœ“Use Managed Identity when connecting to Azure resources (zero secrets to manage)
โœ“For production connections, require approval before use
โœ“Rotate Service Principal secrets every 90 days
โœ“Use Azure Key Vault for secrets instead of pipeline variables
14๐Ÿ†

Best Practices

Enterprise Azure DevOps Patterns

Pipeline Best Practices
โœ“Use YAML pipelines for everything new โ€” Classic only for legacy
โœ“Store azure-pipelines.yml in the same repo as your application code
โœ“Use templates for shared build/deploy logic across microservices
โœ“Use extends templates for mandatory security scans and approvals
โœ“Variable groups linked to Azure Key Vault for secrets (auto-rotation)
โœ“Multi-stage pipelines: Build โ†’ Test โ†’ Staging โ†’ Production in one file
โœ“Environment approvals with branch filters and deployment windows
โœ“Self-hosted agents for private network access and faster builds
Security Best Practices
โœ“Connect Azure Active Directory for SSO and MFA
โœ“Branch policies on main: require PR, reviewers, passing build
โœ“Folder-level service connections (team isolation)
โœ“PATs with minimum scope and 90-day expiration
โœ“Managed Identity for Azure connections (no passwords to rotate)
โœ“Audit logs: Organization Settings โ†’ Auditing โ†’ review who changed what
โœ“Never store secrets in pipeline variables โ€” use Key Vault
โœ“Restrict who can modify production environment approvals
15๐Ÿ’ผ

Interview Questions

30+ Azure DevOps Q&A

Platform & Basics
โ“
What is Azure DevOps?
All-in-one DevOps platform by Microsoft: Repos (Git), Boards (Agile), Pipelines (CI/CD), Artifacts (packages), Test Plans. Available as cloud service or on-premises (Azure DevOps Server).
โ“
Classic vs YAML pipeline?
Classic: UI-based, not in Git, easy to start. YAML: code-based, version-controlled, reviewable in PRs, recommended for production. Classic Releases are legacy; YAML multi-stage is the future.
โ“
What are Branch Policies?
Rules on branches: require PR (no direct push), minimum reviewers, build validation (CI must pass), linked work items, comment resolution. Enforce code quality automatically.
โ“
Organization vs Project?
Organization = company level (users, billing, policies). Project = team/product level (repos, boards, pipelines). One org has many projects.
Pipelines & Deployment
โ“
What is a deployment job?
Special job type with environment, strategy, and lifecycle hooks. Uses deployment: instead of job:. Supports approvals, deployment history, and rollback tracking.
โ“
How do approvals work?
Configured on Environments (not pipelines). When pipeline targets environment \"production\", configured approvers must approve. Pipeline pauses until approval.
โ“
What are Variable Groups?
Shared variable collections usable across multiple pipelines. Can be linked to Azure Key Vault for automatic secret rotation. Created in Library section.
โ“
template vs extends?
template inserts reusable steps (teams can add more). extends wraps entire pipeline (teams only fill parameters). extends enforces organizational standards โ€” teams cannot bypass.
Security & Administration
โ“
What are Service Connections?
Authenticated links to external services (Azure, K8s, Docker). Centrally managed, scoped to pipelines. Use Managed Identity for Azure to avoid password management.
โ“
Self-hosted vs Microsoft-hosted agents?
Microsoft-hosted: managed VMs, fresh each build, no maintenance. Self-hosted: your VMs, access to private networks, persistent tools, faster (no VM spin-up).
โ“
What are PATs?
Personal Access Tokens โ€” scoped authentication tokens for CLI and API access. Each user creates their own. Set minimum permissions and 90-day expiration.
โ“
How to manage permissions?
Layered: Organization (access levels) โ†’ Project (groups: Admin, Contributor, Reader) โ†’ Repo (branch permissions) โ†’ Pipeline โ†’ Environment (deployment approvals). Always follow least privilege.
โ“
Azure DevOps vs Jenkins?
Azure DevOps: full platform (repos + boards + pipelines + artifacts), cloud hosted, tight Azure integration. Jenkins: CI/CD only, self-hosted, 1800+ plugins, more customizable but more maintenance.
โ“
What is Azure Artifacts?
Private package registry inside Azure DevOps. Supports NPM, Maven, NuGet, Python, Universal packages. Teams publish and consume internal packages. Like private Nexus or JFrog.