Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed
- The workflow `init` writes now runs on `ubuntu-24.04` instead of `ubuntu-latest`. GitHub moves `ubuntu-latest` to Ubuntu 26 between October 19 and November 19, 2026, and a new image can change the tools a workflow relies on, such as the `gettext` package the Django extract step installs. A pinned image keeps the translation workflow in your repository running the same way until you choose to move it; GitHub supports the Ubuntu 24 image for two more years. Workflows created by earlier versions are not changed.

## [0.0.80] - 2026-10-08

### Fixed
Expand Down
5 changes: 4 additions & 1 deletion src/utils/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ function buildExtractStep(options: WorkflowOptions): string {
}

const workflowFileName = 'localhero-translate.yml';
// Pinned rather than ubuntu-latest: the generated file lives in the customer's repo,
// where we cannot fix it if a new runner image changes the toolchain under it.
const RUNNER_IMAGE = 'ubuntu-24.04';
const GIT_USER_NAME = 'LocalHero Bot';
const GIT_USER_EMAIL = 'hi@localhero.ai';

Expand Down Expand Up @@ -315,7 +318,7 @@ concurrency:

jobs:
translate:
runs-on: ubuntu-latest
runs-on: ${RUNNER_IMAGE}
permissions:
contents: write
pull-requests: write
Expand Down
8 changes: 8 additions & 0 deletions tests/utils/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ describe('githubService', () => {
expect(checkout?.with).toMatchObject({ 'fetch-depth': 0, 'persist-credentials': false });
});

it('pins the runner image so a GitHub image migration cannot change the toolchain under a generated workflow', async () => {
await createGitHubActionFile('/project', ['locale/**'], undefined, { extractor: 'django', locales: ['sv'] });

const fileContent = (mockFs.writeFile.mock.calls[0] as unknown[])[1] as string;

expect(parse(fileContent).jobs.translate['runs-on']).toBe('ubuntu-24.04');
});

it('handles directory paths without patterns correctly', async () => {
await createGitHubActionFile('/project', ['locales', 'translations/', 'src/i18n']);

Expand Down
Loading