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