feat(github): choose each project's sync label on the GitHub integration page
Summary
On the GitHub integration page, each mapped project now has its own sync label. The synced projects table gets a Sync label column with an edit button. It opens the project's sync settings: auto-sync, only labelled issues, and a label picker that suggests the repository's labels and also accepts any other name. Repository syncs from the page keep the project's label. Before, they reset it to Gauzy every time.
Why
#7083 asks to pick the tags/labels for the GitHub and JIRA integrations from the integration settings. For GitHub the API already stores a per-project label (OrganizationProject.syncTag, isTasksAutoSync, isTasksAutoSyncOnLabel), and the webhook automation filters issues on it. But:
- the GitHub page wrote
syncTag: SyncTags.GAUZYon every Auto sync and Manual sync (view.component.ts, two places). A label set anywhere else was overwritten on the next sync. - the page gave no way to see or change the label.
- a project that syncs only labelled issues but has no label made the automation throw (
project.syncTag.trim()onnull), so none of its issues synced.
JIRA has no task sync at all (#7192), so this PR covers GitHub only. #7083 stays open for the JIRA part.
What changed
@gauzy/contracts: new github-sync-label.ts, shared by the API and the UI:
resolveGithubSyncLabel(syncTag): the project's own label trimmed, orSyncTags.GAUZYwhen it has none.normalizeGithubLabelName,isValidGithubLabelName: GitHub's label rules (one line, at most 50 characters counted as code points, trimmed). PlusGITHUB_LABEL_NAME_MAX_LENGTH.hasGithubSyncLabel(labels, syncLabel): compares trimmed names exactly, the way the sync always compared them.
@gauzy/plugin-integration-github (API): GithubSyncService.shouldSyncIssue matches on resolveGithubSyncLabel(project.syncTag). Projects with a label behave exactly as before. A label-filtering project without a label now syncs on the default label instead of throwing.
@gauzy/plugin-integration-github-ui:
view.component.ts: Auto sync and Manual sync link the project through_linkProjectToRepository. It reads the stored project (GET /organization-projects/:id), then callsPUT /organization-projects/setting/:idwithsyncTag: resolveGithubSyncLabel(stored). The label is read fresh because the project selector's copy can predate a label saved since.- New Sync label column (
GithubProjectSyncLabelComponent, standalone). It shows the label, "All issues" or "Auto-sync off", plus an edit button. - New sync settings dialog (
GithubProjectSyncSettingsComponent, standalone, opened withNbDialogService):- toggles for auto-sync and "only issues with a label"
- a label field (
nbAutocomplete) that suggests the default label, the project's own label, then the labels of the repository's open issues, read from the existing issues endpoint (one page of 100). No new API. If GitHub cannot be read, the field still accepts free text. - an empty field stands for the default label. A name GitHub would refuse is rejected inline.
- with label filtering off, the label is not sent, so the stored one is kept.
- saves through the existing
updateProjectSettingendpoint and permissions, then refreshes the table.
github-project-sync.ts: pure helpers for the sync mode and the label suggestions (collect, dedupe case-insensitively, filter). When a suggested name differs from a repository label only by case, the repository's spelling is offered, so picking it matches the exact-match sync.- Styles use Nebular tokens, plus
--gauzy-text-color-2with a--text-hint-colorfallback. Every registered theme defines these, includingmaterial-lightandmaterial-dark, which lack the Gauzy text and card tokens.
@gauzy/ui-core i18n: 14 new keys under INTEGRATIONS.GITHUB_PAGE.PROJECT_SYNC, translated, in all 14 language files. Lines were only added. Ten files had no GITHUB_PAGE block yet, so it was created there holding only the new keys. ach.json gets the English text, as recent PRs did.
Flags/settings and their defaults
No new setting, column or migration. The PR reuses syncTag, isTasksAutoSync and isTasksAutoSyncOnLabel, and the existing project-setting endpoint and its permissions. Defaults are unchanged:
- A project that never picks a label keeps syncing on
Gauzy. The page still storesGauzyfor a project without a label, as before. - Auto sync and Manual sync still import every open or selected issue. The label filter applies only to the webhook automation, as it always has.
- Label matching stays exact after trimming (case-sensitive), as before.
Tests
All run locally on Node 26.10:
npx jest -c packages/contracts/jest.config.ts --rootDir packages/contracts src/lib/github-sync-label: 28 passed.NODE_OPTIONS=--experimental-vm-modules npx jest -c packages/plugins/integration-github/jest.config.ts --rootDir packages/plugins/integration-github src/lib/github/github-sync: 3 suites, 18 passed. The newgithub-sync.label.spec.ts(10) covers a chosen label, a trimmed label, the default label not matching once a project picks its own, a missing label falling back to the default (it threw before), a label filter that is off, and auto-sync off. The existingcompletionandvisibilityspecs still pass.npx jest -c packages/plugins/integration-github-ui/jest.config.ts --rootDir packages/plugins/integration-github-ui: 6 suites, 42 passed.github-project-sync.spec.ts: sync mode, label suggestions, filtering.project-sync-settings.component.spec.ts: form from the project; saving the chosen label trimmed, the default label when empty, no label when filtering is off; validation blocking save; suggestions from the issues endpoint with typed filtering; fallback when GitHub fails; save errors; cancel.project-sync-label.component.spec.ts: each mode and the edit event.view.component.spec.ts: Auto sync and Manual sync keep a custom label, store the default for a project without one, and the dialog opens and refreshes.
- Type checks:
tsc --noEmitonpackages/contracts/tsconfig.lib.jsonis clean.tsc --noEmitonpackages/plugins/integration-github/tsconfig.lib.jsonshows no errors in the plugin.tsc --noEmitonpackages/plugins/integration-github-ui/tsconfig.spec.jsonis clean.ngc --noEmit(strict templates) on the UI plugin shows no errors in the plugin's files. This ran through a temporary tsconfig that adds thenodeandgoogle.mapstypes, so the compiler gets past the unrelated ui-core type errors and reaches the template checks. A canary error was used to confirm template checks were running.
- Prettier (repository config) passes on every new file.
view.component.tskeeps the formatting differences it already had ondevelop. eslinton the touched files: the contracts helper is clean. On the two new components, ESLint reports only two rules: thelibselector prefix and the OnPush preference. Every component in this plugin usesngx-andChangeDetectionStrategy.Eager, so the new ones follow the plugin.
Manual verification still needed
- I did not run the page against a real GitHub App installation, so these are untested:
- the dialog layout
- the autocomplete dropdown
- the label suggestions coming back from GitHub
- To check it: map a repository, edit a project's label to one the repository uses, open or label an issue on GitHub, and confirm only labelled issues become tasks. Then run Auto sync again and confirm the label is still the one you chose.
Risk and rollback
- Low risk. The change is contained in the GitHub plugins plus additive exports and i18n keys.
- The one behaviour change for existing installs: a project with label filtering on and no label now syncs issues labelled
Gauzythrough the webhook, instead of failing on every webhook. Projects mapped from the GitHub page already storeGauzy, so they see no difference. - Each Auto sync or Manual sync from the page makes one extra request (
GETof the project). - To roll back, revert the PR. Nothing in the database changes shape.
Decisions
- Label matching stays exact (case-sensitive) after trimming. GitHub treats label names case-insensitively, but switching the match would change which issues sync for existing installs. Follow-up: case-insensitive matching, opt-in or announced.
- The bulk "Auto sync" button keeps importing every open issue, even for a project set to "only issues with a label".
isTasksAutoSyncOnLabeldefaults totruein the database, so filtering the bulk import would shrink it for most projects. The label filter stays on the webhook automation only, as before. - No new endpoint for repository labels. Suggestions come from the existing issues endpoint (one page of 100 open issues), and any other label can be typed.
- No new server-side limit on
syncTag. That would be stricter for existing API clients. The UI validates against GitHub's rules instead. - JIRA is out of scope: it has no task sync yet (#7192), so #7083 stays open for that part.
Refs #7083
š¤ Generated with Claude Code