feat(deploy_keys): add LastUsedAt and UsageType to both deploy key structs

What does this MR do?

API::Entities::DeployKey inherits from API::Entities::SSHKey, and two of the fields it inherits are modelled by neither deploy key struct: last_used_at and usage_type. Both are exposed with no condition at all, so every deploy key response of every route on this page carries them and both structs drop them.

The evidence, read from gitlab-org/gitlab at commit e5d23f6d, the tip of master when this was written:

Field Exposed at Sent
last_used_at ssh_key.rb:10 always
usage_type ssh_key.rb:16 always

The project-scope routes render API::Entities::DeployKeysProject, which is expose :deploy_key, merge: true, using: Entities::DeployKey plus can_push, so the merged deploy key keys arrive at the top level and ProjectDeployKey needs the same two fields as the instance one.

The order the entity renders in is id, title, created_at, expires_at, last_used_at, key, usage_type, fingerprint, fingerprint_sha256, so last_used_at belongs beside expires_at and usage_type beside key. I placed each one next to that neighbour rather than reordering ProjectDeployKey, whose existing field order already differs from the entity's: reordering would be invisible to a keyed literal and would break an unkeyed one, and it is not worth that for cosmetics.

One thing I checked and did not change, because the answer surprised me. projects_with_write_access and projects_with_readonly_access are exposed under if: ->(_, options) { options[:include_projects_with_write_access] } and its readonly twin, and the only route that passes those options is GET /deploy_keys, at lib/api/deploy_keys.rb:49. Every project-scope route presents without them. So InstanceDeployKey is right to carry both lists and ProjectDeployKey is right not to, and this MR leaves that alone. The documentation page agrees: the two lists appear in the instance list example and in none of the project ones.

I found this while developing an MCP server on top of this library, https://github.com/jmrplens/gitlab-mcp-server, which currently reads both keys out of the raw response beside the SDK decode.

Is this a breaking change?

No. Two additive fields on each of two response structs. No field is renamed, retyped, removed or moved.

Callers that were reading the zero value of a field they did not have will start seeing the real timestamp and usage type.

How was this tested?

TestGetDeployKey carries usage_type and last_used_at in its fixture and asserts both decoded values, which covers ProjectDeployKey and with it the merged DeployKeysProject shape.

TestListAllDeployKeys does the same for InstanceDeployKey on the first key of the list, leaving the second one without either key so the absent case still decodes to a nil timestamp and an empty string.

go build ./..., go test . and golangci-lint run ./... all pass locally, and gofumpt -l reports nothing on the changed files.

Related to #2300

Merge request reports

Loading
Loading