Add GitHub updates endpoints and permissions
What does this MR do and why?
Adds the backend for the GitHub updates (continuous sync from GitHub) settings and status UI. Only projects imported
while the github_continuous_import feature flag was on have the sync row these endpoints depend on.
Projects::Import::Sync::GithubUpdatesControllerservesstatus,update_nowandstop. Errors return an error code (github_connection_lost,github_updates_not_stoppable,github_updates_not_updatable,github_updates_busy) and a message, which the UI shows. The endpoints build the status withImport::Sync::GithubUpdatesStatusPresenter.- Access uses three new permissions:
read_github_update(Maintainer and Auditor) gatesstatus,update_github_update(Maintainer) gatesupdate_now, andstop_github_update(Maintainer) gatesstop.stopis its own action because a stop can't be undone (needs Authorization team approval as an action outside the preferred set).update_github_updateandstop_github_updateare in theproject:archivedgroup, so archived and deletion-scheduled projects can't be updated or stopped. - A stop request writes a
github_updates_stop_requestedaudit event, because it can't be undone.RequestStopServicenow takescurrent_user:for the audit author. Repeated requests while a stop is already running, and refused requests, write no event. - The endpoints depend only on the sync row, not on
github_continuous_import. While the row exists the project stays read-only, so a flag rollback must not take away the way to stop updates.
Part 2 of 4, split from !263261 (closed).
- Mirroring: hide the mirroring form when mirroring isn't available.
- Backend: permissions, routes, controller, status presenter, stop audit event (this MR).
- Updates component: the Settings > Repository > GitHub updates Vue panel.
- Top banner: the read-only banner on project pages.
References
Related to #628593
Screenshots or screen recordings
Every string this MR adds, shown where it appears in the UI from part 3, for UX and technical writing review. Server messages are real responses from GDK with the database set to each state.
Messages after Update now
| Case | Screenshot |
|---|---|
| Update scheduled | ![]() |
| Refused: updates are not on (state changed since the page loaded) | ![]() |
Messages after Stop GitHub updates
| Case | Screenshot |
|---|---|
| Import still running | ![]() |
| Not in a state that can be stopped | ![]() |
| Connection lost | ![]() |
| Another update is still finishing | ![]() |
How to set up and validate locally
Prerequisites
- Configure GitHub OAuth in GDK:
-
On GitHub, go to Settings > Developer settings > OAuth Apps > New OAuth App. Set Homepage URL to your GDK URL (for example,
https://gdk.test:3000) and Authorization callback URL tohttps://gdk.test:3000/users/auth. This path covers both GitHub sign-in (/users/auth/github/callback) and the import (/users/auth/-/import/github/callback), because GitHub accepts any redirect under the callback URL. Generate a client secret. -
Add the app to
gdk.yml, then rungdk reconfigureandgdk restart:omniauth: github: enabled: true client_id: '<client ID>' client_secret: '<client secret>' -
In a Rails console,
Gitlab::Auth::OAuth::Provider.enabled?(:github)returnstrue.
-
- Enable the feature flag before you authenticate with GitHub:
Feature.enable(:github_continuous_import). GitLab stores the GitHub credential for updates only during the OAuth sign-in while the flag is on. - Have a group on a Premium or Ultimate license to import into. A personal namespace doesn't offer updates.
Import a project with GitHub updates on
- Go to New project > Import project > GitHub and select Authenticate with GitHub. Updates aren't offered when you import with a personal access token.
- Authorize the OAuth app. If you authenticated before enabling the flag, the import fails with "To import with updates on, authorize GitHub again." Authenticate with GitHub again.
- Select Advanced import settings, then Keep this project updated from GitHub.
- Select the Premium or Ultimate group as the target and select Import.
- When the import finishes, check the sync row in a Rails console:
Project.find_by_full_path('<group>/<project>').import_sync_repository.authority_statereturns"provider_canonical".
GitHub can't reach a local GDK with webhooks, so changes made on GitHub reach GitLab only through the periodic repair
pass or update_now.
Validate
This MR has no UI. Call the endpoints from the browser console on any page of the project, signed in as a Maintainer:
const csrf = { 'X-CSRF-Token': document.querySelector('meta[name=csrf-token]').content };
const base = `${location.pathname.split('/-/')[0]}/-/github_updates`;
await (await fetch(`${base}/status`)).json();
await (await fetch(`${base}/update_now`, { method: 'POST', headers: csrf })).json();
await (await fetch(`${base}/stop`, { method: 'POST', headers: csrf })).json();statusreturns the authority state and the state of every data type.update_nowreturnsUpdate scheduled.with the status.- In a Rails console, set the row to
disconnected:Import::Sync::Repository.find_by!(project_id: <id>).disconnect!(:token_revoked).stopreturnsgithub_connection_lost. Restore it with.restore!. - On a throwaway project (a stop can't be undone), call
stop. The project's Secure > Audit events shows the stop request with your user (needs a license with audit events). - Archive the project, or schedule it for deletion:
update_nowandstopreturn 404.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.





