Connection indicator, test action, and remote settings writes on the edit form (monolith/S07 Steps 7-8)

Part of epic &22455 (Repository CRUD, monolith/S07). Covers Steps 7-8 of the Phase 2 (remote) plan, docs/plans/monolith/2026-08-20-repository-crud-remote.md in the artifact-registry repo.

The edit form's remote behavior: the connection indicator with its test action, and the writable settings controls. Both run over the local Apollo layer rather than the real schema, so the flows are drivable in a browser ahead of the AR gates and ahead of the schema steps. Plan Step 10 connects them. All dark behind artifact_registry_ui; no changelog. Both steps add user-facing strings, externalized, with the regenerated locale/gitlab.pot.

Files sit under ee/app/assets/javascripts/packages_and_registries/artifact_registry/, with Jest specs under ee/spec/frontend/packages_and_registries/artifact_registry/.

Implementation details

Step 7: Connection indicator and the test action on the edit form (type::feature)

  • repositories/components/remote_source_section.vue (Modify): the indicator and the action.
  • repositories/components/connection_indicator.vue (Create): the health status, its timestamp, and the upstream status, as one component the monolith/S05 detail page can mount later.
  • graphql/mutations/test_repository_connection.mutation.graphql (Create): wholly @client on a local-prefixed field, so graphql-verify reports it as a client query and skips it, and it cannot collide with the mutation plan Step 4 mounts. It also needs its own operation name, which @graphql-eslint/unique-operation-name enforces app-wide.
  • graphql/typedefs.graphql and graphql/mock_resolvers.js (Modify): the local mutation, its input and payload types, and the resolver answering three outcomes - a reachable verdict, a not-reachable verdict, and the unavailable failure.
  • The indicator renders the stored health status and the time it was last checked, conveying the verdict in text rather than by color or icon alone.
  • While the probe runs, the action is disabled and reports that a probe is running, the indicator keeps showing the stored verdict rather than emptying, and the rest of the form stays interactive.
  • On the service-unavailable outcome the page-level alert renders and the indicator is left as it was, because nothing was established that would justify changing it.
  • The same action on the repository detail page is not this step's. It is a monolith/S05 plan amendment, to raise with that plan's author.

Step 8: Remote settings writes on the edit form (type::feature)

  • repositories/components/remote_source_section.vue (Modify): writable controls, the credential inputs and remove action, the bounds, and the URL-change warning.
  • repositories/edit/repositories_edit_form.vue (Modify): send the per-format settings input on the update.
  • graphql/mutations/update_remote_repository.mutation.graphql (Create): wholly @client on a local-prefixed field, beside the shared hosted document. Marking the shared document @client would route hosted writes through the mock and regress a shipped path, which is why a second document exists.
  • graphql/typedefs.graphql and graphql/mock_resolvers.js (Modify): the local update mutation, its input, its payload including the credentials-cleared field, and its resolver.
  • The second document reuses the shared document's payload alias, because cache_update.js addresses the payload by name (data.updateRepository). The mock resolver echoes the values the form submitted rather than fabricating any, because cache_config.js keys the repository on name alone, so mock values would otherwise surface in the shipped list for a seeded repository during review.
  • Credentials are never echoed, so the inputs start empty and an empty form means unchanged. The remove action beside the indicator is what sets removeCredentials, so removal is asked for rather than implied. The shape follows the format: a username and password pair for Maven and the container family, a bearer token for npm, rendered as a password input.
  • Cache windows are numeric inputs bounded as AR bounds them: the artifact window from 0 and the metadata window from 1, both to 32767.
  • Before the write, the form warns that changing the upstream URL evicts the cached artifacts and clears the stored credentials, unless the same submission supplies new ones.
  • No change to graphql/utils/cache_update.js. evictUpdatedRepositoryDetails already evicts the whole details entry after any successful update, and the edit form already passes it. This step asserts that coverage rather than adding to it.
  • The Maven snapshot revalidation setting gets no control, deliberately. A reader who notices the gap should not close it by adding one.

Acceptance

Step 7:

  • The action issues the test mutation, and the answered verdict replaces the indicator's stored values rather than rendering beside them.
  • While the probe runs, the action is disabled and the indicator still shows the stored verdict.
  • A not-reachable verdict renders as a result and leaves submit enabled.
  • The service-unavailable outcome renders the page alert and leaves the indicator unchanged.
  • The arriving result is announced.

Step 8:

  • An edit that changes only the cache window sends only that field.
  • An edit that supplies credentials sends the object, one that uses the remove action sets removeCredentials, and an untouched credential field sends neither.
  • A cache-window value outside AR's bounds is refused at the field.
  • The URL-change warning renders before submit rather than in the success message.
  • A URL change leaves the connection indicator showing the reset health status rather than the old host's verdict.
  • After an update that changed the URL, the repository's cached artifact fields are gone, which the existing whole-entry eviction already delivers. Asserted against a mock cache built from cache_config.js.
  • The credentials-cleared signal is shown when AR reports it, and not when a URL change supplied new credentials.
  • The section still renders no cache-eviction action.

Dependencies

  • The Phase 2 plan merge request must merge before any merge request here opens.
  • Both steps depend on plan Step 6, in the "Remote create route ... and the prefilled source section" issue. They are siblings of each other and unordered, so remote_source_section.vue needs a deliberate rebase rather than a mechanical one: Step 8 rewrites the controls Step 6 renders read-only.
  • No dependency on the GraphQL write steps. Both run over the local Apollo layer.
  • No AR contract gate applies to the mocked path. That is what makes the stored-credentials indicator with its remove action, and the cache-period bounds, demonstrable here rather than after AR moves.
  • Blocks the closing issue (plan Steps 9 and 10).
Edited by 🤖 GitLab Bot 🤖