feat(users): add external to instance service account create and update

Closes #2310

GitLab 19.5 lets you set external when you create or update an instance service account (gitlab-org/gitlab!254608 (merged)). With client-go, Go users couldn't set it. The service accounts returned by ListServiceAccounts and UpdateInstanceServiceAccount also didn't say if they are external.

Now:

  • CreateServiceAccountUserOptions and UpdateServiceAccountOptions have External.
  • ServiceAccount has External, so those two methods return it.

false matters here. GitLab creates service accounts as external by default, so to get a non-external one you have to send "external": false. client-go sends it when you set External: new(false).

  1. UpdateServiceAccountOptions is shared by Groups.UpdateServiceAccount and Users.UpdateInstanceServiceAccount. I added External there instead of making a new options type. Changing the UpdateInstanceServiceAccount signature would be a breaking change, and those wait for 4.0. The group endpoint doesn't accept external, so GitLab ignores it there. The field comment says it's only for UpdateInstanceServiceAccount. I can switch to a separate options type if you prefer.
  2. GitLab versions before 19.5 ignore the parameter.

I left the group and project service account responses out. external on them can go in a follow-up.

!3063 (closed) also edits the ServiceAccount struct, so one of the two may need a small rebase.

How I tested

I wrote a small Go program that creates a service account with External: new(false), updates it with External: new(true), and lists service accounts, all against a local test server. The server prints each request.

On main, the program doesn't compile:

unknown field External in struct literal of type gitlab.CreateServiceAccountUserOptions
unknown field External in struct literal of type gitlab.UpdateServiceAccountOptions
sa.External undefined (type *gitlab.ServiceAccount has no field or method External)
list[0].External undefined (type *gitlab.ServiceAccount has no field or method External)

On this branch, false is sent, and External is read back from the update and list responses:

server got: POST /api/v4/service_accounts body={"username":"bot","external":false}
create err: <nil>
server got: PATCH /api/v4/service_accounts/7 body={"external":true}
update err=<nil> External=true
server got: GET /api/v4/service_accounts body=
list err=<nil> External=true

The create unit test now checks the request body, including "external": false. I added an update test that checks the request body and the returned External, for true and false.

$ go test -count=1 -run 'ServiceAccount' .
ok  	gitlab.com/gitlab-org/api/client-go/v3	0.008s

gofumpt -l on the changed files and go vet . printed nothing. I didn't run make reviewable, golangci-lint or the -race tests locally. The pipeline runs them.

I couldn't test against a real GitLab 19.5 instance. Creating an instance service account needs admin access, and I don't have such an instance.

Implemented with AI assistance; I reviewed and tested the changes.

Edited by Hamza Hassanain

Merge request reports

Loading
Loading