1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package client
4
5import "slices"
6
7// Contract features this client relies on, as listed by
8// ServerService.GetVersion. A server without one still works for everything
9// else: the CLI warns instead of failing.
10const (
11 // FeatureMarkReady permits marking draft merge requests ready.
12 FeatureMarkReady = "merge_requests.ready"
13 // FeatureIgnoreChecks permits merging with checks bypassed.
14 FeatureIgnoreChecks = "merge_requests.ignore_checks"
15 // FeatureRepoUpdate is RepoService.UpdateRepo (`ermite repo edit`).
16 FeatureRepoUpdate = "repo.update"
17 // FeatureEventsResume is EventService.Watch with resume_after, which
18 // `ermite watch` uses to continue after a reconnection.
19 FeatureEventsResume = "events.resume"
20 // FeatureMergeRequests is MergeRequestService (`ermite mr`).
21 FeatureMergeRequests = "merge_requests"
22 // FeatureMergeDeleteBranch is MergeMergeRequest with delete_source_branch
23 // (`ermite mr merge --delete-branch`).
24 FeatureMergeDeleteBranch = "merge_requests.delete_branch"
25 // FeatureIssues is IssueService, RepoSettings.issues and the issue:write
26 // scope (`ermite issue`, `ermite repo edit --issues`).
27 FeatureIssues = "issues"
28 // FeatureSigningKey is ServerService.GetSigningKey (`ermite signing-key`).
29 FeatureSigningKey = "signing_key"
30 // FeatureSession is SessionService (`ermite web login`, `web logout`).
31 FeatureSession = "session"
32 // FeaturePasskeys is SessionService.ListPasskeys and RemovePasskey
33 // (`ermite web passkey`). A server lists it only when passkeys are
34 // available (https public URL with a DNS host name).
35 FeaturePasskeys = "passkeys"
36 // FeatureTokenBranchPrefixes is Token.branch_prefixes and
37 // CreateTokenRequest.branch_prefixes (`ermite token create --branch-prefix`).
38 // A server without it ignores the field and would create an unlimited
39 // token: `token create --branch-prefix` reads the features first and
40 // refuses when it is missing (the main guard), and also checks the token it
41 // gets back (a backstop).
42 FeatureTokenBranchPrefixes = "token.branch_prefixes"
43 // FeatureCIRuns is RunService (`ermite run`), FeatureCIRunners its runner
44 // calls (`ermite runner`).
45 FeatureCIRuns = "ci.runs"
46 FeatureCIRunners = "ci.runners"
47 // FeatureCISecrets is SecretService, VariableService and EnvironmentService
48 // (`ermite secret`, `variable`, `environment`).
49 FeatureCISecrets = "ci.secrets"
50 // FeatureCIDispatch is RunService.DispatchWorkflow (`ermite workflow run`).
51 FeatureCIDispatch = "ci.dispatch"
52 // FeatureCIWorkflows is RunService.ListWorkflows, DisableWorkflow and
53 // EnableWorkflow (`ermite workflow list|disable|enable`).
54 FeatureCIWorkflows = "ci.workflows"
55 // FeatureCIArtifacts is ArtifactService (`ermite run artifacts`,
56 // `run download`).
57 FeatureCIArtifacts = "ci.artifacts"
58 // FeatureCommitSignatures is TrustedKeyService and Commit.verification
59 // (`ermite signing-key trust`).
60 FeatureCommitSignatures = "commit_signatures"
61 // FeatureMergeability is MergeRequest.mergeability and the
62 // merge_request_mergeability event.
63 FeatureMergeability = "merge_requests.mergeability"
64 // FeatureAutoMerge is MergeRequestService.EnableAutoMerge and
65 // CancelAutoMerge, RepoSettings.allow_auto_merge and the auto-merge events
66 // (`ermite mr merge --auto`).
67 FeatureAutoMerge = "merge_requests.auto_merge"
68)
69
70// UsedFeatures lists the features the CLI uses, in the order they are reported.
71func UsedFeatures() []string {
72 return []string{FeatureRepoUpdate, FeatureEventsResume, FeatureMergeRequests, FeatureMergeDeleteBranch, FeatureIssues, FeatureMergeability, FeatureSigningKey, FeatureSession, FeatureTokenBranchPrefixes, FeatureCIRuns, FeatureCIRunners, FeatureCISecrets, FeatureCIDispatch, FeatureCIWorkflows, FeatureCIArtifacts, FeaturePasskeys, FeatureCommitSignatures, FeatureAutoMerge}
73}
74
75// MissingFeatures returns the features the CLI uses that have is lacking.
76func MissingFeatures(have []string) []string {
77 var missing []string
78 for _, f := range UsedFeatures() {
79 if !slices.Contains(have, f) {
80 missing = append(missing, f)
81 }
82 }
83 return missing
84}