Skip to content

Commit 7345aa0

Browse files
authored
Add status subcommand (#201)
* go.mod Pull fatih/colors and carabiner-dev/vclocator Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Add status subcommand Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Fix unrelated linter nit Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Add long command help for status Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Expose policy.GetPolicy() (and use it) Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Use Controls.Names() in status subcmd Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Expose policy.ComputeEligibleSlsaLevel() Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Update status subcmd to use ComputeEligibleSlsaLevel Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> * Rename controls struct to AllLevelControls Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]> --------- Signed-off-by: Adolfo Garcia Veytia (puerco) <[email protected]>
1 parent 7ccf09f commit 7345aa0

File tree

9 files changed

+254
-24
lines changed

9 files changed

+254
-24
lines changed

go.work.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSY
3737
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
3838
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
3939
github.com/CycloneDX/cyclonedx-go v0.9.1/go.mod h1:NE/EWvzELOFlG6+ljX/QeMlVt9VKcTwu8u0ccsACEsw=
40+
github.com/CycloneDX/cyclonedx-go v0.9.2 h1:688QHn2X/5nRezKe2ueIVCt+NRqf7fl3AVQk+vaFcIo=
4041
github.com/CycloneDX/cyclonedx-go v0.9.2/go.mod h1:vcK6pKgO1WanCdd61qx4bFnSsDJQ6SbM2ZuMIgq86Jg=
4142
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
4243
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
@@ -80,6 +81,7 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ
8081
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
8182
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
8283
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
84+
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
8385
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
8486
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
8587
github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+KONo8/KrELABiY=
@@ -90,15 +92,19 @@ github.com/buildkite/interpolate v0.1.3/go.mod h1:UNVe6A+UfiBNKbhAySrBbZFZFxQ+DX
9092
github.com/buildkite/roko v1.2.0/go.mod h1:23R9e6nHxgedznkwwfmqZ6+0VJZJZ2Sg/uVcp2cP46I=
9193
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
9294
github.com/carabiner-dev/ampel v0.0.0-20250209210344-7b306497c927/go.mod h1:KJBPGPxyllTdgWoMW/lD3KBa/KAvVznZXzgUQUyPFxs=
95+
github.com/carabiner-dev/ampel v0.0.1-pre9.0.20250521004715-85b637ea9193 h1:wD6nGN7gq5IQJ4qFF0V4Jpu8B2FM+9ZnwlUqN5scWxk=
9396
github.com/carabiner-dev/ampel v0.0.1-pre9.0.20250521004715-85b637ea9193/go.mod h1:sQEeCRjbikSoqB1+VmZmWK2R0u2NdauEXDab+VlS8pQ=
9497
github.com/carabiner-dev/github v0.0.0-20250210222226-442fdacc1d16 h1:6ESg7ESScHJp/e4zHO1a1y6XDAJYTcK9N06mqbqBvUg=
9598
github.com/carabiner-dev/github v0.0.0-20250210222226-442fdacc1d16/go.mod h1:hAfka+26SmZJoTfpWUnIeQUVKFYcT45RUPXqBsqxWpU=
9699
github.com/carabiner-dev/github v0.2.2/go.mod h1:J7VqMAUewwRQH6r6HMDmVNf39f/z7H5iyTzOfC8am9A=
97100
github.com/carabiner-dev/hasher v0.1.0/go.mod h1:+X5f8ts4Q/ubkmsWQGzCQwPxtJx39AoqoT/IlDR7M9Q=
98101
github.com/carabiner-dev/hasher v0.2.2/go.mod h1:bM7reKZ5gGEY4Bbcd3Lr2KhrtqNkEhJOmQ4ptGasnFY=
99102
github.com/carabiner-dev/jsonl v0.2.0/go.mod h1:H0ac1z6a6AEvRx1+laZrztAdGoYuB/CVlGXK5nHHQyI=
103+
github.com/carabiner-dev/openeox v0.0.0-20250430212020-e3a5beb42ddd h1:WEQbh3d2h0x2BIwrIQWeBqlGugjVfIgXSKX/4mNxkjA=
100104
github.com/carabiner-dev/openeox v0.0.0-20250430212020-e3a5beb42ddd/go.mod h1:40KVT1ee6L8VoWT44RvAQ0AtG91MFr5/zBzTmNiXQWY=
105+
github.com/carabiner-dev/osv v0.0.0-20250124012120-b8ce4531cd92 h1:BJ9+OCNezZGkU8SrGC3oB7Tj+J0JsonwfZztcgUav6c=
101106
github.com/carabiner-dev/osv v0.0.0-20250124012120-b8ce4531cd92/go.mod h1:o7jXwi/fFZ9mQlvVlog0kcvyEkwQT3eWmVQmrorBGpE=
107+
github.com/carabiner-dev/vcslocator v0.2.2 h1:UXhuMUxtDiwGzfCxvpNJXRyqUY8qZl0+Ug3TjJluS4s=
102108
github.com/carabiner-dev/vcslocator v0.2.2/go.mod h1:/67gubbzxtg25MIg/eRlmBkHExFDqyVZ2Dj0VJatHwE=
103109
github.com/cavaliercoder/badio v0.0.0-20160213150051-ce5280129e9e/go.mod h1:V284PjgVwSk4ETmz84rpu9ehpGg7swlIH8npP9k2bGw=
104110
github.com/cavaliercoder/go-rpm v0.0.0-20200122174316-8cb9fd9c31a8/go.mod h1:AZIh1CCnMrcVm6afFf96PBvE2MRpWFco91z8ObJtgDY=
@@ -275,6 +281,7 @@ github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF
275281
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
276282
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
277283
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
284+
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE=
278285
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481/go.mod h1:yKZQO8QE2bHlgozqWDiRVqTFlLQSj30K/6SAK8EeYFw=
279286
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
280287
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -293,8 +300,10 @@ github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9
293300
github.com/open-policy-agent/opa v0.68.0/go.mod h1:5E5SvaPwTpwt2WM177I9Z3eT7qUpmOGjk1ZdHs+TZ4w=
294301
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
295302
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
303+
github.com/openvex/go-vex v0.2.5 h1:41utdp2rHgAGCsG+UbjmfMG5CWQxs15nGqir1eRgSrQ=
296304
github.com/openvex/go-vex v0.2.5/go.mod h1:j+oadBxSUELkrKh4NfNb+BPo77U3q7gdKME88IO/0Wo=
297305
github.com/owenrumney/go-sarif v1.1.1/go.mod h1:dNDiPlF04ESR/6fHlPyq7gHKmrM0sHUvAGjsoh8ZH0U=
306+
github.com/package-url/packageurl-go v0.1.1 h1:KTRE0bK3sKbFKAk3yy63DpeskU7Cvs/x/Da5l+RtzyU=
298307
github.com/package-url/packageurl-go v0.1.1/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c=
299308
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
300309
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
@@ -307,6 +316,7 @@ github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1
307316
github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg=
308317
github.com/prometheus/prometheus v0.51.0/go.mod h1:yv4MwOn3yHMQ6MZGHPg/U7Fcyqf+rxqiZfSur6myVtc=
309318
github.com/protobom/protobom v0.5.0/go.mod h1:HL47tggz7SXYXgNm3WjQQrWB6iOirYnrATsXAEyTUkI=
319+
github.com/protobom/protobom v0.5.2 h1:GQacWLer4tDskyjQpqbglXkT3ZlNy7AJCw/S2XZkVS8=
310320
github.com/protobom/protobom v0.5.2/go.mod h1:io5yUKGWBqGa2sx1n7aVPg+tG13Hun9oMz4Y+EjNjjc=
311321
github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
312322
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
@@ -323,6 +333,7 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR
323333
github.com/sigstore/cosign/v2 v2.4.1/go.mod h1:GvzjBeUKigI+XYnsoVQDmMAsMMc6engxztRSuxE+x9I=
324334
github.com/sigstore/fulcio v1.6.3/go.mod h1:5SDgLn7BOUVLKe1DwOEX3wkWFu5qEmhUlWm+SFf0GH8=
325335
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
336+
github.com/spdx/tools-golang v0.5.5 h1:61c0KLfAcNqAjlg6UNMdkwpMernhw3zVRwDZ2x9XOmk=
326337
github.com/spdx/tools-golang v0.5.5/go.mod h1:MVIsXx8ZZzaRWNQpUDhC4Dud34edUYJYecciXgrw5vE=
327338
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
328339
github.com/spiffe/go-spiffe/v2 v2.1.3/go.mod h1:eVDqm9xFvyqao6C+eQensb9ZPkyNEeaUbqbBpOhBnNk=
@@ -485,6 +496,7 @@ k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt
485496
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
486497
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
487498
sigs.k8s.io/release-sdk v0.12.1/go.mod h1:nnB4tt1g0VXMUCIYzDzPVqNI896OQrWipE6WbyZ6FSk=
499+
sigs.k8s.io/release-sdk v0.12.2 h1:ncuHwUu8VWcZVVrNkjoUR8xGo6ibHg+AM6uMMD+IwuQ=
488500
sigs.k8s.io/release-sdk v0.12.2/go.mod h1:tlJgWPJLeRbWOvcyq1XrCZmLe8Yfn3H5U/LNtmBa0Nc=
489501
sigs.k8s.io/release-utils v0.8.5/go.mod h1:qsm5bdxdgoHkD8HsXpgme2/c3mdsNaiV53Sz2HmKeJA=
490502
sigs.k8s.io/release-utils v0.9.0/go.mod h1:xZoCJyajMJ0wtgGXWuznbC1r9dw7iJzMp/+dCkf1UGw=

sourcetool/cmd/root.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Copyright © 2025 NAME HERE <EMAIL ADDRESS>
44
package cmd
55

66
import (
7+
"fmt"
78
"os"
89

910
"github.com/spf13/cobra"
@@ -48,6 +49,7 @@ func getVerifier() attest.Verifier {
4849
func Execute() {
4950
err := rootCmd.Execute()
5051
if err != nil {
52+
fmt.Printf("Error: %v\n", err)
5153
os.Exit(1)
5254
}
5355
}
@@ -60,4 +62,6 @@ func init() {
6062
rootCmd.PersistentFlags().StringVar(&githubToken, "github_token", "", "the github token to use for auth")
6163
rootCmd.PersistentFlags().StringVar(&expectedIssuer, "expected_issuer", "", "The expected issuer of attestations.")
6264
rootCmd.PersistentFlags().StringVar(&expectedSan, "expected_san", "", "The expect san of attestations.")
65+
66+
addStatus(rootCmd)
6367
}

sourcetool/cmd/status.go

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// SPDX-FileCopyrightText: Copyright 2025 Carabiner Systems, Inc
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package cmd
5+
6+
import (
7+
"context"
8+
"errors"
9+
"fmt"
10+
"slices"
11+
"strings"
12+
13+
"github.com/fatih/color"
14+
"github.com/spf13/cobra"
15+
16+
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/attest"
17+
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/ghcontrol"
18+
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/policy"
19+
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/slsa"
20+
)
21+
22+
var w = color.New(color.FgHiWhite, color.BgBlack).SprintFunc()
23+
24+
type repoOptions struct {
25+
owner string
26+
repository string
27+
}
28+
29+
func (ro *repoOptions) Validate() error {
30+
errs := []error{}
31+
if ro.owner == "" {
32+
errs = append(errs, errors.New("repository owner not set"))
33+
}
34+
if ro.repository == "" {
35+
errs = append(errs, errors.New(""))
36+
}
37+
return errors.Join(errs...)
38+
}
39+
40+
// AddFlags adds the subcommands flags
41+
func (ro *repoOptions) AddFlags(cmd *cobra.Command) {
42+
cmd.PersistentFlags().StringVar(
43+
&ro.repository, "repository", "", "name of the repository",
44+
)
45+
46+
cmd.PersistentFlags().StringVar(
47+
&ro.owner, "owner", "", "user or oganization that owns the repo",
48+
)
49+
}
50+
51+
func (bo *branchOptions) Validate() error {
52+
errs := []error{}
53+
errs = append(errs, bo.repoOptions.Validate())
54+
55+
if bo.branch == "" {
56+
return errors.New("branch not set")
57+
}
58+
return errors.Join(errs...)
59+
}
60+
61+
// AddFlags adds the subcommands flags
62+
func (bo *branchOptions) AddFlags(cmd *cobra.Command) {
63+
bo.repoOptions.AddFlags(cmd)
64+
65+
cmd.PersistentFlags().StringVar(
66+
&bo.branch, "branch", "", "name of the branch",
67+
)
68+
}
69+
70+
type branchOptions struct {
71+
repoOptions
72+
branch string
73+
}
74+
75+
// statusOptions
76+
type statusOptions struct {
77+
branchOptions
78+
commit string
79+
}
80+
81+
// Validate checks the options
82+
func (so *statusOptions) Validate() error {
83+
errs := []error{}
84+
errs = append(errs, so.branchOptions.Validate())
85+
86+
return errors.Join(errs...)
87+
}
88+
89+
// AddFlags adds the subcommands flags
90+
func (so *statusOptions) AddFlags(cmd *cobra.Command) {
91+
so.branchOptions.AddFlags(cmd)
92+
cmd.PersistentFlags().StringVar(
93+
&so.commit, "commit", "", "commit to check",
94+
)
95+
}
96+
97+
// TODO(puerco): Most of the logic in this subcommand (except maybe the output)
98+
// will be moved to a sourcetool object in the future to consolidate it into
99+
// a reusable library.
100+
func addStatus(parentCmd *cobra.Command) {
101+
opts := &statusOptions{}
102+
statusCmd := &cobra.Command{
103+
Short: "Check the SLSA Source status of a repo/branch",
104+
Long: `
105+
sourcetool status: Check the SLSA Source status of a repo/branch
106+
107+
The status subcommand reads the current controls enabled for a branch
108+
and reports the SLSA source level that the repository can claim. This
109+
command is intended to help maintainers implementing SLSA controls
110+
understand the next steps to secure their repos and progress in their
111+
SLSA journey.
112+
`,
113+
Use: "status",
114+
SilenceUsage: false,
115+
SilenceErrors: true,
116+
PreRunE: func(cmd *cobra.Command, args []string) error {
117+
return nil
118+
},
119+
RunE: func(cmd *cobra.Command, args []string) error {
120+
// Validate the options
121+
if err := opts.Validate(); err != nil {
122+
return err
123+
}
124+
125+
cmd.SilenceUsage = true
126+
127+
ctx := context.Background()
128+
ghc := ghcontrol.NewGhConnection(opts.owner, opts.repository, opts.branch)
129+
130+
// If we didn't get a commit, assume HEAD
131+
if opts.commit == "" {
132+
commitSha, err := ghc.GetLatestCommit(ctx, opts.branch)
133+
if err != nil {
134+
return fmt.Errorf("fetching latest commit hash: %w", err)
135+
}
136+
opts.commit = commitSha
137+
}
138+
139+
// Get the active controls
140+
activeControls, err := ghc.GetBranchControls(ctx, opts.commit, ghcontrol.BranchToFullRef(opts.branch))
141+
if err != nil {
142+
return fmt.Errorf("checking status: %w", err)
143+
}
144+
145+
// We need to manually check for PROVENANCE_AVAILABLE
146+
attestor := attest.NewProvenanceAttestor(
147+
ghcontrol.NewGhConnection(opts.owner, opts.repository, opts.branch),
148+
attest.GetDefaultVerifier(),
149+
)
150+
151+
// Fetch the attestation, if found then add the control
152+
attestation, _, err := attestor.GetProvenance(ctx, opts.commit, "refs/heads/"+opts.branch)
153+
if err != nil {
154+
return fmt.Errorf("attempting to read provenance from commit: %w", err)
155+
}
156+
if attestation != nil {
157+
activeControls.Controls.AddControl(&slsa.Control{
158+
Name: slsa.ProvenanceAvailable,
159+
})
160+
}
161+
162+
// Check if there is a policy:
163+
pcy, _, err := policy.NewPolicyEvaluator().GetPolicy(ctx, ghc)
164+
if err != nil {
165+
return fmt.Errorf("checking if the repository has a policy %w", err)
166+
}
167+
168+
// Compute the maximum level possible:
169+
toplevel := policy.ComputeEligibleSlsaLevel(activeControls.Controls)
170+
171+
title := fmt.Sprintf("SLSA Source Status for %s/%s", opts.owner, opts.repository)
172+
fmt.Printf("")
173+
fmt.Println(w(title))
174+
fmt.Println(strings.Repeat("=", len(title)))
175+
176+
for _, c := range slsa.AllLevelControls {
177+
fmt.Printf("%-35s ", c)
178+
if slices.Contains(activeControls.Controls.Names(), c) {
179+
fmt.Println("✅")
180+
} else {
181+
fmt.Println("🚫")
182+
}
183+
}
184+
185+
fmt.Println("")
186+
fmt.Printf("%-35s ", "Repo policy found:")
187+
if pcy == nil {
188+
fmt.Println("🚫")
189+
} else {
190+
fmt.Println("✅")
191+
}
192+
fmt.Println("")
193+
194+
fmt.Println(w("Current SLSA Source level: " + toplevel))
195+
fmt.Println("")
196+
197+
return nil
198+
},
199+
}
200+
opts.AddFlags(statusCmd)
201+
parentCmd.AddCommand(statusCmd)
202+
}

sourcetool/go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.24.3
44

55
require (
66
github.com/carabiner-dev/bnd v0.2.0
7+
github.com/fatih/color v1.18.0
78
github.com/go-git/go-git/v5 v5.16.2
89
github.com/google/go-github/v69 v69.2.0
910
github.com/in-toto/attestation v1.1.2-0.20250128181946-c0b4d86cf712
@@ -30,7 +31,6 @@ require (
3031
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
3132
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
3233
github.com/emirpasic/gods v1.18.1 // indirect
33-
github.com/fatih/color v1.18.0 // indirect
3434
github.com/fsnotify/fsnotify v1.8.0 // indirect
3535
github.com/go-chi/chi v4.1.2+incompatible // indirect
3636
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
@@ -67,6 +67,8 @@ require (
6767
github.com/kevinburke/ssh_config v1.2.0 // indirect
6868
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
6969
github.com/mailru/easyjson v0.9.0 // indirect
70+
github.com/mattn/go-colorable v0.1.13 // indirect
71+
github.com/mattn/go-isatty v0.0.20 // indirect
7072
github.com/mitchellh/mapstructure v1.5.0 // indirect
7173
github.com/oklog/ulid v1.3.1 // indirect
7274
github.com/opencontainers/go-digest v1.0.0 // indirect

sourcetool/go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4
272272
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
273273
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
274274
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
275+
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
275276
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
276277
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
277278
github.com/migueleliasweb/go-github-mock v1.3.0 h1:2sVP9JEMB2ubQw1IKto3/fzF51oFC6eVWOOFDgQoq88=
@@ -448,6 +449,8 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
448449
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
449450
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
450451
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
452+
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
453+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
451454
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
452455
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
453456
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

sourcetool/pkg/ghcontrol/checklevel_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,7 @@ func TestBuiltinBranchControls(t *testing.T) {
265265
control := controlStatus.Controls.GetControl(tt.expectedControl)
266266
if control == nil {
267267
t.Fatalf("expected controls to contain %v, got %+v", tt.expectedControl, controlStatus.Controls)
268-
}
269-
if !control.Since.Equal(priorTime) {
268+
} else if !control.Since.Equal(priorTime) {
270269
t.Fatalf("expected control.Since %v, got %v", priorTime, control.Since)
271270
}
272271
})

0 commit comments

Comments
 (0)