Skip to content

GitHub Actions Ubuntu 26.04 Tutorial: Test Before ubuntu-latest Changes

Test GitHub Actions on Ubuntu 26.04 before ubuntu-latest migrates, identify hidden runner dependencies, and choose between migration and pinning.

GitHub Actions Ubuntu 26.04 Tutorial: Test Before ubuntu-latest Changes

On this page

GitHub made its Ubuntu 26.04 runner generally available on September 17, 2026, and the change has a deadline hidden inside an otherwise familiar setting: ubuntu-latest will move from Ubuntu 24.04 to Ubuntu 26.04 between October 19 and November 19. A workflow can therefore keep the same YAML while its operating system changes underneath it. This GitHub Actions Ubuntu 26.04 tutorial shows how to test that migration now, identify dependencies that could break, and pin a workflow when you need more control.Β 

The safest way to think about this change is as an environment migration rather than a normal package update. GitHub-hosted runners are virtual machines provisioned for individual jobs, and their preinstalled tools are maintained as part of GitHub's runner images. Ubuntu 26.04 changes those images, including software versions and some removals, so a project that quietly depends on something already installed can behave differently even when its source code has not changed.Β 

Why ubuntu-latest can change a working build

The runs-on value in a GitHub Actions job selects the operating system image used to execute that job. With ubuntu-latest, you are intentionally choosing a moving label rather than a fixed Ubuntu release. GitHub says the label currently points to Ubuntu 24.04 and will migrate to Ubuntu 26.04 during the October 19 to November 19, 2026 window, which means a successful build today does not guarantee that the same environment will be present next month.Β 

That flexibility is convenient for ordinary projects, but it can hide environmental dependencies. A workflow may assume a particular compiler, scripting runtime, command-line utility, or system package exists because it has always been present on the hosted image. When the runner changes, that assumption becomes a compatibility problem rather than a source-code bug. GitHub specifically warns that updated or removed tools and versions can break workflows that depend on the previous image.Β 

Test Ubuntu 26.04 without changing your production workflow

The first step is to leave your existing ubuntu-latest jobs alone and add a temporary compatibility job that uses the explicit ubuntu-26.04 label. This lets you compare the new environment before GitHub moves the floating label. The x64 Ubuntu 26.04 image is fully supported for production workflows, and GitHub also provides ubuntu-26.04-arm for Arm64 jobs.Β 

Suppose your repository currently has a basic Node.js workflow like this:

name: Node CI

on:
push:
pull_request:

jobs:
test:
runs-on: ubuntu-latest

```
steps:
  - uses: actions/checkout@v6
  - uses: actions/setup-node@v7
    with:
      node-version: 24
  - run: npm ci
  - run: npm test

Do not replace ubuntu-latest immediately. Copy the job into a temporary workflow or branch and change only the runner label:

name: Ubuntu 26 Compatibility
```

on:
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-26.04

```
steps:
  - uses: actions/checkout@v6
  - uses: actions/setup-node@v7
    with:
      node-version: 24
  - run: npm ci
  - run: npm test

The important detail is that your application runtime is still explicitly selected with actions/setup-node. That separates your project's Node.js requirement from whatever version happens to be installed globally on the runner. GitHub documents runner images as collections of preinstalled software, while its hosted-runner guidance also shows how setup actions can be used to install the version your workflow actually requires.Β 

Run the compatibility job and treat failures as environment clues

Trigger the temporary workflow manually from the Actions tab. A successful run tells you that the tested path works on Ubuntu 26.04; it does not prove every path in the repository is compatible. That distinction matters for repositories with separate build, packaging, deployment, integration-test, and release jobs. Test the jobs that use different system commands or toolchains rather than assuming one green job covers the entire project.

When a job fails, read the first meaningful environment-related error rather than immediately changing application code. A message saying a command is missing, a package cannot be found, or a compiler behaves differently can indicate an image difference. GitHub's runner-image repository publishes the installed software for each image, making it possible to compare what is available on Ubuntu 24.04 and Ubuntu 26.04 before deciding how to fix the workflow.Β 

Use the explicit runner label for diagnosis. Testing with ubuntu-26.04 gives you a stable target while the ubuntu-latest migration is still scheduled for the future.

Check the tools your project depends on

The difference between the two images is broader than the Ubuntu release number. The currently published Ubuntu 24.04 image includes tools such as Node.js 22 and 24, Python 3.10 through 3.14 in its cached tool set, Kotlin 2.4.20, Julia, Miniconda, Fastlane, Mercurial, Pulumi, and several other utilities. The Ubuntu 26.04 image has a different software inventory, so a workflow that relies on a preinstalled tool should be checked explicitly rather than relying on memory.

Some of the changes are especially easy to miss because the workflow never installs those tools directly. GitHub's earlier Ubuntu 26.04 image announcement documented removals including Miniconda, Julia, Fastlane, Mercurial, Pulumi, MediaInfo, and Sphinx Open Source Search Server. GitHub also noted that some of these removals were made for maintenance reasons, while in one case it pointed users toward a dedicated GitHub Action instead of the globally installed tool.Β 

A practical audit is therefore to search your repository for commands that come from the runner rather than your package manager. Look for commands such as python, ruby, go, java, terraform, pulumi, jq, database clients, browser binaries, and other utilities invoked directly from run: steps. Then ask a simple question for each one: does the workflow install the required version, or does it merely assume the hosted image provides it?

Make the workflow install what it really needs

The strongest fix for an environment dependency is usually to make the dependency explicit. Instead of assuming a particular runtime is already available, use an official setup action or install the package during the workflow. For example, the Node.js workflow above already uses actions/setup-node, which means a change in the runner's preinstalled Node versions is less likely to alter the application's selected runtime. GitHub's hosted-runner documentation explicitly supports installing additional software as part of a job when the default image does not provide what you need.Β 

The same principle applies to command-line utilities. If your workflow needs a package supplied through Ubuntu's package manager, install it rather than counting on it remaining in the image:

- name: Install required system tools
```

run: |
sudo apt-get update
sudo apt-get install -y jq

This adds a small amount of work to the job, but it makes the dependency visible in source control. A future runner image can change without silently removing that requirement from your build environment because the workflow itself now declares what it needs. GitHub's documentation provides the same general mechanism for installing additional software on hosted Ubuntu runners.Β 

Compare the actual runner environment when a build behaves differently

When a compatibility test fails, add a diagnostic step before changing the build logic. Printing the operating-system release and versions of the tools used by the failing job can turn a vague "CI broke" report into a concrete environment comparison.

- name: Show runner environment
run: |
uname -a
cat /etc/os-release
node --version
npm --version
python3 --version
gcc --version | head -n 1
git --version

This is particularly useful when your build passes on Ubuntu 24.04 but fails on Ubuntu 26.04. You can compare the logs side by side and determine whether the failure comes from an operating-system change, a tool version, or your own workflow assumptions. Because the runner-image repository publishes the installed software inventory, you can then check the documented image contents instead of guessing which dependency changed.Β 

Do the same for project-specific tooling. A JavaScript build might need a particular package manager, while a native extension may depend on a compiler or system library. The more your build depends on globally preinstalled software, the more useful these diagnostics become.

Test both normal and ARM64 workflows when architecture matters

GitHub also provides an Ubuntu 26.04 Arm64 runner through ubuntu-26.04-arm. This is a separate environment, not simply Ubuntu 26.04 running with a different label, so projects with native dependencies should test it independently. The hosted-runner reference lists both x64 and Arm64 Ubuntu 26.04 labels, with the Arm64 option available for workflows that need that architecture.Β 

Architecture-sensitive projects can fail for reasons that have nothing to do with the Ubuntu migration itself. Native Node.js modules, compiled Python extensions, Docker images, binary downloads, and scripts that assume x64 can behave differently on Arm64. If your production workflow does not use Arm64, this branch can be ignored; if it does, make it an explicit test target rather than treating x64 success as proof of compatibility.

Choose whether to migrate or pin the workflow

After testing, there are two technically valid ways to handle the upcoming change. You can keep ubuntu-latest and make the workflow independent of undocumented image assumptions, or you can change the job to an explicit version such as ubuntu-26.04. GitHub itself recommends testing against Ubuntu 26.04 before the migration and says that projects not ready to move can pin to ubuntu-24.04.Β 

Pinning changes the trade-off: you gain a stable operating-system target, but you become responsible for deliberately deciding when to move again. Keeping ubuntu-latest reduces that maintenance because GitHub continues moving the label to a newer supported release, but the environment can change without a workflow-file edit. Neither strategy removes the need to declare application-level dependencies explicitly.

If you are ready for Ubuntu 26.04, an explicit configuration is simple:

jobs:
test:
runs-on: ubuntu-26.04

If you need more time, pin to the current release instead:

jobs:
test:
runs-on: ubuntu-24.04

The important part is to make the choice intentional. Leaving ubuntu-latest in place without testing means GitHub's scheduled migration becomes your compatibility test, while an explicit label makes the timing of your migration part of your own release process.

Test the migration again after fixing every failure

A single successful run is not enough if your repository has several workflows. Repeat the test for pull requests, scheduled jobs, release workflows, deployment jobs, and any matrix builds that use different language versions or operating systems. A matrix can be especially useful because one job may succeed while another uses a different compiler, database client, or packaging tool. GitHub's workflow syntax supports explicit runner labels, so each job can target the environment it actually needs.Β 

After the fixes, keep the compatibility workflow around until you are satisfied that your important paths have been exercised. You can also make it a scheduled check during the migration window, although the migration itself does not happen uniformly for every repository at one instant. GitHub says the ubuntu-latest move will roll out gradually from October 19 through November 19, 2026.Β 

There is one final reason not to postpone this work. The source code for a repository can remain unchanged while the hosted build machine changes, so a clean Git diff does not necessarily mean a clean CI environment. Test the explicit Ubuntu 26.04 label now, move hidden dependencies into the workflow, and decide whether your project should follow ubuntu-latest or pin a release before the October 19 migration begins.

U

Written by

Usman Ali

I enjoy discovering software that can make work easier, faster, or simply more enjoyable. I like testing applications, exploring new features, following software updates, and finding useful tools that people may not know about. I prefer writing practical guides that show readers how to actually use the software.

14 posts published

All posts by this author

0 Comments

No comments yet. Be the first to share your thoughts.

Join the conversation

Log in or create a free account to leave a comment. You can edit or delete your own comments any time.