Skip to content

Translation tracker: auto close issue on PR merged and closed - #1582

Draft
aashishpanthi wants to merge 24 commits into
processing:v1from
aashishpanthi:feature/translation-tracker/auto-close-issue
Draft

Translation tracker: auto close issue on PR merged and closed#1582
aashishpanthi wants to merge 24 commits into
processing:v1from
aashishpanthi:feature/translation-tracker/auto-close-issue

Conversation

@aashishpanthi

@aashishpanthi aashishpanthi commented Aug 23, 2026

Copy link
Copy Markdown
Member

Summary

The translation tracker opens a GitHub issue for every outdated or missing translation. Until now, those issues stayed open after the translation actually landed, so maintainers had to close them by hand and there was backlog.

This adds a translation-auto-close.yml workflow that runs when a PR touching translated content is merged. It works out which tracker issues the PR resolves, marks off the languages that were translated, and closes each issue once nothing is left to translate.

Addresses #1404.

How an issue is found

Relying on Resolves #123 did not worked well with real contributors: most translation PRs either use no linking keyword or mention the issue somewhere other than the body. So any #123 is treated as a candidate, and it is looked for in:

  • the PR title and body
  • review summaries (maintainers can/do write "this handles #123" during review)
  • issues that cross-reference the PR from their own thread
  • pasted https://github.com/<owner>/<repo>/issues/123 links

Also, comments written by bots are ignored, so the tracker's own automation cannot feed itself.

How false positives are avoided

Matching every #123 is deliberately greedy, so candidates are filtered:

  • fenced code blocks and inline code spans are stripped first, which removes most hex colors and code samples
  • owner/repo#123 cross-repo references and #123abc are not matched; numbers are capped at five digits because color codes are six digits and we are in four digits, we'll reach six digits in years (needs attention)
  • the PR's own number is skipped
  • each remaining candidate must exist, must not be a pull request, and must carry the needs translation label

How an issue is updated

Which languages a PR translated is derived from its changed file paths, for example src/content/examples/es/... means Spanish. For each such language, the action removes the lang-<code> label and strikes that language's line in the issue body. The issue is closed only when no lang-* labels are left.

One tracker issue often covers several languages for the same English file, which creates a wrinkle: GitHub closes an issue natively the instant a PR saying Fixes #123 is merged, even when only one of four languages was done. The action detects this and reopens the issue, leaving a comment naming the languages still working.

Testing

npm run test:auto-close runs the flow against a mocked GitHub API and covers: keyword-free references, the reopen path, comment-sourced references, bot filtering, cross-references, noise rejection, referenced pull requests, and PRs with no translation files.

@aashishpanthi

Copy link
Copy Markdown
Member Author

Note: This branches off the stub-file-generation PR. So, #1473 should be merged first, then this.

name: Translation Auto-Close

on:
pull_request:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @aashishpanthi , I see one blocker here for which I'm not very sure.

For any PR opened from a fork (which is how virtually all external translation contributors submit), GitHub downgrades GITHUB_TOKEN to read-only regardless of the permissions: block. This workflow needs issues: write to remove labels, edit the body, comment, and close/reopen, all of those API calls (removeLabel, issues.update, createComment) will return 403 for fork PRs.

The whole motivation of the PR ("real contributors" not using linking keywords) implies fork-based PRs, so as written the feature might work only for maintainers pushing branches inside the repo.

Can we test this on a fork?

cc: @ksen0 do you have any views here?

const { getLanguageDisplayName, getTranslationPath } = require('./utils');

// List all files changed in a merged PR (paginated).
async function listPullRequestFiles(octokit, owner, repo, pullNumber) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function returns every file including status: "removed"/"renamed", and neither identifyLanguagesFromFiles nor the verifiedLanguages filter checks status:

const verifiedLanguages = languages.filter((lang) => {
const paths = expectedPaths.get(lang);
if (!paths || paths.length === 0) return false;
return paths.some((p) => changedFileNames.includes(p)); // matches removed files too
});

A PR that deletes src/content/examples/es/foo.mdx would strike Spanish, remove lang-es, and potentially close the tracker issue - the opposite of the truth. Filter to file.status === 'added' || 'modified' (or exclude removed) before deriving languages and verifying paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants