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:

YAML
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:

YAML
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.

  1. Decide where the code, the planning and the build and release live. For each of the three decisions, give the reason in one sentence.
  2. Assign the solution to one of the four combinations A to D.
  3. Sketch in a table which connection delivers which function (link, pull request visibility, trigger).
  4. 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.

  1. Take the Azure Pipelines file below.
  2. Write the same intent as a GitHub Actions workflow: two jobs, the second only after the first, only for the branch main.
  3. Name the term of the other world in a comment on every line.
YAML
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

YAML
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.exe on Windows, GitHub Actions uses PowerShell; whoever needs the old behavior sets shell: 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