Loading
feat(ssh-key): add --replace flag to ssh-key add
Description
glab ssh-key add fails with fingerprint_sha256: [has already been taken] when the key is already registered on the account, even when that key has expired. The API has no update endpoint for SSH keys, so re-registering a key meant running glab ssh-key list --show-id, glab ssh-key delete <id>, and then glab ssh-key add again.
This MR adds a --replace flag to glab ssh-key add:
- It parses the public key being added and computes its SHA256 fingerprint.
- It goes through all SSH keys on the account (paginated) and looks for a key with the same fingerprint.
- If it finds one, it deletes that key and then adds the new key with the given title, usage type, and expiration date.
- If no key matches, it just adds the key.
- If the add fails after the delete, the error tells you the ID of the key that was deleted, so you're not left wondering where it went.
Without --replace, nothing changes: no extra API calls, same error on duplicates.
Smaller changes along the way:
- The
addcommand now passescmd.Context()to the client-go calls throughgitlab.WithContext. - The flag registrations now go through a local
flvariable, which is the repo convention.
glab ssh-key add ~/.ssh/id_ed25519.pub -t "laptop" --expires-at 2027-01-01 --replaceRelated Issues
Related to #8577 (closed)
This covers only the --replace part of the issue. Not in this MR, could be follow-ups:
- Showing the key ID in
glab ssh-key listby default. Today you need--show-id. - A single rotate command that generates a key, registers it, removes the expired one, and updates Git's
user.signingkey.
How has this been tested?
- New table-driven unit tests in
internal/commands/ssh-key/add/add_test.gothat use client-go mocks (gitlabtesting). They cover:- Replace when a key matches.
- No matching key.
- A match on the second page.
- A key that can't be parsed.
- List, delete, and add failures.
- The no-flag path, which makes no list or delete calls.
- The existing
Test_AddSSHKeycases still pass. TheirAddSSHKeymock expectations now accept the context request option. go test ./internal/commands/ssh-key/...,go build ./...,golangci-lint run ./internal/commands/ssh-key/..., andgo run ./scripts/comment-overlap(no findings in the changed files).make gen-docs, with the regenerateddocs/source/ssh-key/add.mdcommitted.
Screenshots (if appropriate):
n/a