Nordlicht Reisen GmbH, a fictional travel agency, has so far maintained its booking portal in a single tool. Now two teams are joining, and each has its own habits: one team lives on GitHub, the other has its task planning in Azure Boards. The head of engineering wants to know whether that is a problem. The answer of the AZ-400 exam is: no problem, if you know both worlds and know who can do what and how they work together.
This lesson is the map of the course. It does not teach any operation yet, but puts things in order: which services exist on both sides, what the terms are called there, which combinations are common, and how you decide what belongs where. The later lessons go deeper into every point.
Prior knowledge: K3 teaches pipelines for a .NET application: GitHub Actions in lesson 3.7.1, Azure Pipelines with YAML, templates and variable groups in lesson 3.7.2. There you already know the building blocks trigger, pool, stages, jobs and steps, and that an agent is called a runner on GitHub. Here we use that as a springboard for the comparison. The course does not repeat those lessons.
Note: All statements come from the documentation of Microsoft Learn and of GitHub; the pages are listed under "Further reading". The commands and YAML files of this lesson were not run; they come from the reference of Microsoft and GitHub.
The services of both worlds side by side
Azure DevOps is Microsoft's platform for software teams. It consists of five services, which Microsoft describes like this: Azure Boards (work planning), Azure Repos (source code), Azure Pipelines (build and release), Azure Test Plans (planned and exploratory testing) and Azure Artifacts (package feeds). In addition there are a wiki and dashboards. The top-level organizing concept is the project; there you can switch the services on and off individually.
GitHub has cut the same tasks differently. GitHub's introduction lists: repositories, issues and milestones for planning, Projects for managing projects, pull requests for changes, automated workflows for testing and deployment, Packages for publishing software packages, security features and Discussions.
| Task | GitHub | Azure DevOps |
|---|---|---|
| Plan and track work | Issues, milestones, Projects (table, board, roadmap) | Azure Boards: work items, boards, backlogs, sprints, queries, delivery plans |
| Source code | Repository | Azure Repos: unlimited private Git repositories (also TFVC) |
| Build, test, deliver | GitHub Actions (workflows) | Azure Pipelines (YAML or classic) |
| Packages | GitHub Packages, container registry | Azure Artifacts: NuGet, npm, Maven, Python, Cargo, Universal Packages |
| Manual and exploratory tests | no dedicated service | Azure Test Plans |
| Documentation | Markdown in the repository, wiki per repository | Wiki per project, Markdown in the repository |
| Metrics | Insights of Projects, activity of the repository, metrics of Actions | Dashboards with widgets, Analytics, Power BI |
| Security | Dependabot, code scanning, secret scanning (GitHub Advanced Security) | GitHub Advanced Security for Azure DevOps |
| Discussion | Discussions | Comments in work items and pull requests |
Two rows deserve a second look. Test Plans is not a dedicated service on GitHub: whoever wants to plan manual tests and link them to requirements and bugs uses Test Plans in Azure DevOps (Microsoft names there the linking of requirements to test cases and bugs, queries for test suites and a table-like interface). And for security, the same product family exists on both sides; how it fits together is taught in lesson 5.4.
The structure: account, organization, project, repository
The structure differs, and the exam asks about it:
| Level | GitHub | Azure DevOps |
|---|---|---|
| Identity | GitHub account; in companies an organization, with GitHub Enterprise also with sign-in through an identity provider | Microsoft account or Microsoft Entra ID account |
| Frame | Organization (or personal account) | Organization (https://dev.azure.com/<name>) |
| Workspace | Repository (issues and Projects belong to the repository or to the organization) | Project (contains boards, repos, pipelines, artifacts, wiki) |
| Permissions | Roles on repository and organization | Security groups, access levels and permissions per project (lesson 5.2) |
Remember the difference between repository and project: an Azure DevOps project can contain many repositories and has boards and pipelines in common for all of them. A GitHub repository contains its code, its issues and its workflows; a GitHub organization brings many repositories together.
For identity, Microsoft states: Azure DevOps organizations can be connected to Microsoft Entra ID when you sign in with a work or school account; the organization is then connected automatically. Customers of GitHub Enterprise Cloud who sign in to GitHub and Azure DevOps with the same Microsoft Entra tenant get the access level GitHub Enterprise in Azure DevOps at no extra charge; Azure DevOps checks this at the first sign-in and every 24 hours after that. Only users of GitHub Enterprise Cloud are recognized, not those of GitHub Enterprise Server.
Translating the terms
Whoever moves from one world to the other stumbles over names first. GitHub's migration guide from Azure Pipelines to GitHub Actions maps the most important terms:
| Term | Azure Pipelines | GitHub Actions |
|---|---|---|
| Machine on which a job runs | Agent; you select your own agents through capabilities | Runner; you select your own (self-hosted) ones through labels |
| Stages | stages, in the same YAML file | do not exist as a keyword: each stage gets its own workflow file |
| Jobs | jobs: steps one after the other on a VM or in a container, in parallel by default | jobs: the same model |
| Dependency of jobs | dependsOn |
needs |
| Script step | script, bash or pwsh |
run, optionally with shell |
| Task or action | task: with inputs |
uses: with with |
| Condition | condition: with functions such as eq() |
if: with operators such as == |
| Reuse | reusable tasks (and templates, lesson 4.4) | reusable actions, also through the Marketplace |
Three notes from the same page belong here. First: GitHub Actions requires you to split stages into separate YAML workflow files. Second: the default shell on Windows is cmd.exe in Azure Pipelines and PowerShell in GitHub Actions; whoever needs the behavior of cmd sets shell: cmd. Third: GitHub Actions requires explicit job definitions, so even a pipeline with only one job needs a full jobs: block. The page does not map templates, reusable workflows, variables, secrets and environments; they come in lessons 4.4, 4.7 and 5.3.
A small example shows the translation. First the Azure Pipelines version:
jobs:
- job: build
steps:
- script: dotnet build --configuration Release
- job: test
dependsOn: build
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
steps:
- script: dotnet test
And the same intent as a GitHub Actions workflow:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dotnet build --configuration Release
test:
needs: build
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dotnet test
The pipeline lists job names as job: in a list, the workflow names them as keys of jobs:. The workflow names the runner with runs-on and fetches the code with a separate step (actions/checkout); the pipeline names its pool elsewhere (pool, lesson 3.7.2 from K3). Lesson 3.7.1 from K3 showed this for an application; here the mapping is enough for you.
How both work together
In practice, everything rarely runs in one world. Microsoft describes the connection points on the page "About GitHub integration". There are four common combinations:
| Combination | Code | Planning | Build and release | When it fits |
|---|---|---|---|---|
| A: everything on GitHub | GitHub | Issues, Projects | GitHub Actions | the team lives on GitHub and needs no reports from Azure Boards |
| B: everything on Azure DevOps | Azure Repos | Azure Boards | Azure Pipelines | the team has boards, Test Plans and reports and no reason to move the code |
| C: code on GitHub, planning in Azure Boards | GitHub | Azure Boards | Actions or Azure Pipelines | planning needs backlogs, sprints or delivery plans, but the code is on GitHub |
| D: code on GitHub, pipelines in Azure Pipelines | GitHub | Issues or Boards | Azure Pipelines | the pipeline needs features of Azure Pipelines, such as centrally managed templates or sources outside GitHub |
Azure Boards and GitHub
For the integration of Azure Boards and GitHub, Microsoft names these functions: link work items with commits, pull requests, branches and issues; open linked objects on the board; see pull requests (draft, review status, status of the checks) in the "Development" section of a work item; mention pull requests with ! in texts; automatically create "Integrated in build" links for YAML pipelines; put status badges of Azure Boards in the README file of a GitHub repository; and synchronize GitHub issues with work items of Azure Boards using a GitHub Action. How that works is taught in lessons 1.1 and 1.2.
The connection runs through the Azure Boards app for GitHub. It authenticates and acts as an app instead of as an individual person; according to Microsoft, the advantage over older ways with OAuth or a personal access token is that team members can change without the connection depending on a single person.
Azure Pipelines and GitHub
Azure Pipelines can build, test, package and deliver the code of a GitHub repository. Microsoft names: builds for pull requests with feedback as a comment in the pull request, manual starting by comment in the pull request, checking drafts (drafts in the pr trigger), restarting failed builds, builds of pull requests from forks, GitHub-specific tasks such as "GitHub Release" and "Download GitHub Release", build tags for tracing sources. Connecting a repository to Azure Pipelines and the trigger rules are taught in lesson 4.1.
For GitHub Enterprise Server, Microsoft says there are differences: there is no app like the one for GitHub.com, you need a personal access token, user name and password, or OAuth; the protections for contributions from forks (for example, no secrets passed to running jobs) are not available; comment triggers and GitHub Checks do not exist, status reports are simple statuses.
Tools of the other world even without a connection
Finally, note two things that do not depend on the connection. Azure Pipelines cannot replace GitHub Actions and vice versa; both run side by side, and a repository can have workflows and a pipeline. And the security of every connection depends on the permissions: a service connection to Azure, an app installation on GitHub, an access token. Lesson 5.1 covers this.
Choosing a deployment automation solution
The exam asks: which solution fits which requirement? For the toolchain of Azure Landing Zones, Microsoft gives a recommendation that serves as a starting point:
- GitHub Enterprise with repository, GitHub Advanced Security and GitHub Advanced Security for Azure DevOps as the foundation for code and security.
- GitHub Actions for automation, if the repositories are on GitHub.
- Azure Pipelines for more complex scenarios: when code from outside GitHub is needed or central management of workflow templates and build pipelines is required.
- Azure Boards for planning, integrated with Azure Pipelines for GitHub repositories.
- GitHub Packages for packages and container images, Azure Artifacts for a feed with review, permissions and an audit log.
That is a draft, not an obligation. The decision table sums it up:
| If ... | then ... | because ... |
|---|---|---|
| the team uses only GitHub and the repositories are there | GitHub Actions | workflows live with the code and need no second platform |
| the pipeline fetches code from several sources or needs central templates for many teams | Azure Pipelines, also for GitHub repositories | Microsoft recommends it for complex scenarios and central template management |
| the team needs backlogs, sprints, delivery plans and Power BI reports, but the code stays on GitHub | Azure Boards for GitHub with the app | work items can be linked to commits and pull requests |
| manual tests must be planned and linked to requirements | Azure Test Plans | GitHub has no dedicated service for that |
| packages with review, permission and upstream are needed | Azure Artifacts (lesson 3.1) | feeds, views and upstream sources are its core |
| the code is on GitHub Enterprise Server | a personal access token, user name and password, or OAuth for the connection | there is no app for Server and no fork protections |
| only one organization, one plan and one vendor are allowed | everything in one world | two worlds need two permission models and two billings |
For identity, the practical rule is: for Azure DevOps Services, Microsoft recommends sign-in through Microsoft Entra as the default, for users as well as for automation. Which identity is suited for what is taught in lesson 5.1.
Cost and clean-up
This lesson creates nothing in Azure and nothing that costs money over time. The exercises work with paper and with a small example on your machine.
- If you created a repository in Exercise 2, delete it again after the exercise (lesson 0.1: delete a repository, check with
gh repo view). - If you created an Azure DevOps project, delete it or keep it for module D1. It stays free within the free tier.
Exercise 1: Choosing tools for the booking portal
This is a design task: requirement, decision with justification, sketch.
The requirement. Nordlicht Reisen GmbH has two teams. The team "Portal" (six people) maintains the booking portal, has its code on GitHub and wants to leave it there. The team "Betrieb" (German for operations; four people) plans maintenance work in sprints and needs reports on completed work. Engineering wants two things: every change to the portal should be traceable from the request to delivery, and the pipelines for the portal and for three other small services should come from one centrally maintained collection of templates. There is one Azure subscription.
- Decide where the code, the planning and the build and release live. For each of the three decisions, give the reason in one sentence.
- Assign the solution to one of the four combinations A to D.
- Sketch in a table which connection delivers which function (link, pull request visibility, trigger).
- Name one limit or risk of your decision.
How to check it: Your answer contains one combination, justifies each of the three decisions with a statement from this lesson, names the connections (for example, the Azure Boards app for GitHub) and names a limit (for example: two permission models).
Solution 1
Decisions:
| Question | Decision | Reason |
|---|---|---|
| Code | GitHub | the team "Portal" wants to stay there; a move would add nothing for the requirement |
| Planning | Azure Boards for both teams in one project | sprints and reports are its core; the link to GitHub commits and pull requests is documented |
| Build and release | Azure Pipelines with a shared collection of templates | Microsoft recommends Azure Pipelines when central management of templates is needed; four services share one collection |
Combination: C with D: code on GitHub, planning in Azure Boards, pipelines in Azure Pipelines.
Connections:
| Connection | Delivers |
|---|---|
| App Azure Boards for GitHub | linking of work items with commits and pull requests (AB#123), pull request visibility, branch from the work item |
| Azure Pipelines with a GitHub repository | build for pull requests, feedback as a check in the pull request, "Integrated in build" link on the work item |
| shared repository for templates | one source for the pipelines of all four services (lesson 4.4) |
Limit: The team works in two permission models (GitHub roles and Azure DevOps groups) and has two billings; changing identity costs time. An alternative would be combination A with reusable workflows, if reports from Azure Boards could be given up (lesson 4.4).
Exercise 2: Translating a pipeline into the world of GitHub Actions
You translate with the term table, without running anything.
- Take the Azure Pipelines file below.
- Write the same intent as a GitHub Actions workflow: two jobs, the second only after the first, only for the branch
main. - Name the term of the other world in a comment on every line.
jobs:
- job: pruefen
steps:
- script: dotnet format --verify-no-changes
- job: bauen
dependsOn: pruefen
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
steps:
- script: dotnet build --configuration Release
How to check it: Your workflow has jobs: with two keys, needs: instead of dependsOn:, if: instead of condition:, run: instead of script:, one runs-on: per job and an explicit step for the checkout. Every line has a comment.
Solution 2
jobs:
pruefen: # job: pruefen
runs-on: ubuntu-latest # in Azure Pipelines: pool
steps:
- uses: actions/checkout@v4 # fetches the code (uses: instead of task:)
- run: dotnet format --verify-no-changes # script:
bauen:
needs: pruefen # dependsOn:
if: github.ref == 'refs/heads/main' # condition: eq(...)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dotnet build --configuration Release
The solution is a translation according to the terms of the migration guide. The course has not verified that the workflow runs in this state. In production, you pin actions to a commit instead of a movable tag (K3, lesson 3.7.1).
Typical mistakes
- Expecting stages as a keyword in GitHub Actions. GitHub Actions has no
stages; the guide says to split stages into separate workflow files. - Windows scripts behave differently. Azure Pipelines uses
cmd.exeon Windows, GitHub Actions uses PowerShell; whoever needs the old behavior setsshell: cmd. - A single job without a
jobs:block. GitHub Actions requires explicit job definitions, even with only one job. - The Boards connection shows an empty list of repositories. According to Microsoft, this is often because the GitHub organization has restricted access for third-party apps or access for the app to the organization has not been granted yet (status "Access request pending"). An organization owner or administrator must grant it.
- Connecting one GitHub repository to several Azure DevOps organizations. Microsoft advises against it: it can lead to unexpected links with
AB#.
What you can do now
You match the services of GitHub and Azure DevOps to each other and know the structure of both worlds: account and organization, repository and project. You translate terms such as agent and runner, dependsOn and needs, task and uses. You know the four combinations of both tools and the integrations between Azure Boards, Azure Pipelines and GitHub, including the limits with GitHub Enterprise Server. And you justify the choice of a solution for automating deployment with Microsoft's recommendation: GitHub Actions when the repositories are on GitHub, Azure Pipelines for complex scenarios and central templates.
Further reading
- What is Azure DevOps?:
https://learn.microsoft.com/azure/devops/user-guide/what-is-azure-devops - About GitHub integration:
https://learn.microsoft.com/azure/devops/cross-service/github-integration - What is the Azure Boards-GitHub integration?:
https://learn.microsoft.com/azure/devops/boards/github/ - Build GitHub Enterprise Server repositories:
https://learn.microsoft.com/azure/devops/pipelines/repos/github-enterprise - DevOps toolchain (Azure Landing Zones):
https://learn.microsoft.com/azure/cloud-adoption-framework/ready/considerations/devops-toolchain - Authentication guidance for Azure DevOps:
https://learn.microsoft.com/azure/devops/organizations/security/authentication-guidance - User and permissions management FAQs:
https://learn.microsoft.com/azure/devops/organizations/accounts/faq-user-and-permissions-management - Migrating from Azure Pipelines to GitHub Actions:
https://docs.github.com/en/actions/migrating-to-github-actions/manually-migrating-to-github-actions/migrating-from-azure-pipelines-to-github-actions - About GitHub and Git:
https://docs.github.com/en/get-started/start-your-journey/about-github-and-git