Skip to content

Commit ae1367f

Browse files
authored
Fix upgrade bug for GitHub Actions container refs (#85)
There was a bug with "upgrade" wherein GitHub Actions container refs were losing their "docker://" prefix. This also introduces a new "-pin" flag to the "upgrade" command, which can be used to skip pinning upgraded refs.
1 parent c6c53a9 commit ae1367f

File tree

13 files changed

+124
-18
lines changed

13 files changed

+124
-18
lines changed

command/command_gen.go

Lines changed: 6 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

command/command_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func Test_loadYAMLFiles(t *testing.T) {
2020
"c.yml": "",
2121
"circleci.yml": "",
2222
"cloudbuild.yml": "",
23+
"docker.yml": "",
2324
"drone.yml": "",
2425
"github-crazy-indent.yml": "github.yml",
2526
"github-issue-80.yml": "",

command/upgrade.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type UpgradeCommand struct {
3838
flagConcurrency int64
3939
flagParser string
4040
flagOut string
41+
flagPin bool
4142
}
4243

4344
func (c *UpgradeCommand) Desc() string {
@@ -55,6 +56,7 @@ func (c *UpgradeCommand) Flags() *flag.FlagSet {
5556
"maximum number of concurrent resolutions")
5657
f.StringVar(&c.flagParser, "parser", "actions", "parser to use")
5758
f.StringVar(&c.flagOut, "out", "", "output path (defaults to input file)")
59+
f.BoolVar(&c.flagPin, "pin", true, "pin resolved upgraded versions (defaults to true)")
5860

5961
return f
6062
}
@@ -94,8 +96,10 @@ func (c *UpgradeCommand) Run(ctx context.Context, originalArgs []string) error {
9496
return fmt.Errorf("failed to upgrade refs: %w", err)
9597
}
9698

97-
if err := parser.Pin(ctx, res, par, files.nodes(), c.flagConcurrency); err != nil {
98-
return fmt.Errorf("failed to pin upgraded refs: %w", err)
99+
if c.flagPin {
100+
if err := parser.Pin(ctx, res, par, files.nodes(), c.flagConcurrency); err != nil {
101+
return fmt.Errorf("failed to pin upgraded refs: %w", err)
102+
}
99103
}
100104

101105
for _, f := range files {

parser/actions.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@ import (
1212

1313
type Actions struct{}
1414

15+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
16+
func (a *Actions) DenormalizeRef(ref string) string {
17+
isContainer := strings.HasPrefix(ref, resolver.ContainerProtocol)
18+
ref = resolver.DenormalizeRef(ref)
19+
if isContainer {
20+
return "docker://" + ref
21+
}
22+
return ref
23+
}
24+
1525
// Parse pulls the GitHub Actions refs from the documents.
1626
func (a *Actions) Parse(nodes []*yaml.Node) (*RefsList, error) {
1727
var refs RefsList

parser/circleci.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
type CircleCI struct{}
1313

14+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
15+
func (c *CircleCI) DenormalizeRef(ref string) string {
16+
return resolver.DenormalizeRef(ref)
17+
}
18+
1419
// Parse pulls the CircleCI refs from the documents. Unfortunately it does not
1520
// process "orbs" because there is no documented API for resolving orbs to an
1621
// absolute version.

parser/cloudbuild.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
type CloudBuild struct{}
1313

14+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
15+
func (c *CloudBuild) DenormalizeRef(ref string) string {
16+
return resolver.DenormalizeRef(ref)
17+
}
18+
1419
// Parse pulls the Google Cloud Build refs from the documents.
1520
func (c *CloudBuild) Parse(nodes []*yaml.Node) (*RefsList, error) {
1621
var refs RefsList

parser/drone.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
type Drone struct{}
1313

14+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
15+
func (d *Drone) DenormalizeRef(ref string) string {
16+
return resolver.DenormalizeRef(ref)
17+
}
18+
1419
// Parse pulls the Drone Ci refs from the documents.
1520
func (d *Drone) Parse(nodes []*yaml.Node) (*RefsList, error) {
1621
var refs RefsList

parser/gitlabci.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111

1212
type GitLabCI struct{}
1313

14+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
15+
func (c *GitLabCI) DenormalizeRef(ref string) string {
16+
return resolver.DenormalizeRef(ref)
17+
}
18+
1419
// Parse pulls the image references from GitLab CI configuration files. It does
1520
// not support references with variables.
1621
func (c *GitLabCI) Parse(nodes []*yaml.Node) (*RefsList, error) {

parser/parser.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const (
2323
// Parser defines an interface which parses references out of the given yaml
2424
// node.
2525
type Parser interface {
26+
DenormalizeRef(ref string) string
2627
Parse(nodes []*yaml.Node) (*RefsList, error)
2728
}
2829

@@ -220,11 +221,12 @@ func Upgrade(ctx context.Context, res resolver.Resolver, parser Parser, nodes []
220221
merrLock.Unlock()
221222
}
222223

223-
denormLatest := resolver.DenormalizeRef(latest)
224+
denormRef := parser.DenormalizeRef(ref)
225+
denormLatest := parser.DenormalizeRef(latest)
224226

225227
for _, node := range nodes {
226228
node.LineComment = appendOriginalToComment(node.LineComment, denormLatest)
227-
node.Value = denormLatest
229+
node.Value = strings.Replace(node.Value, denormRef, denormLatest, 1)
228230
}
229231
}()
230232
}

parser/tekton.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ import (
1111

1212
type Tekton struct{}
1313

14+
// DenormalizeRef changes the resolved ref into a ref that the parser expects.
15+
func (t *Tekton) DenormalizeRef(ref string) string {
16+
return resolver.DenormalizeRef(ref)
17+
}
18+
1419
// Parse pulls the Tekton Ci refs from the documents.
15-
func (d *Tekton) Parse(nodes []*yaml.Node) (*RefsList, error) {
20+
func (t *Tekton) Parse(nodes []*yaml.Node) (*RefsList, error) {
1621
var refs RefsList
1722
for i, node := range nodes {
18-
if err := d.parseOne(&refs, node); err != nil {
23+
if err := t.parseOne(&refs, node); err != nil {
1924
return nil, fmt.Errorf("failed to parse node %d: %w", i, err)
2025
}
2126
}
@@ -48,17 +53,17 @@ func (d *Tekton) parseOne(refs *RefsList, node *yaml.Node) error {
4853

4954
return nil
5055
}
51-
func (d *Tekton) findSpecs(refs *RefsList, node *yaml.Node) error {
56+
57+
func (d *Tekton) findSpecs(refs *RefsList, node *yaml.Node) {
5258
for i, specsMap := range node.Content {
5359
if specsMap.Value == "spec" {
5460
specs := node.Content[i+1]
5561
d.findImages(refs, specs)
5662
}
5763
}
58-
return nil
5964
}
6065

61-
func (d *Tekton) findImages(refs *RefsList, node *yaml.Node) error {
66+
func (d *Tekton) findImages(refs *RefsList, node *yaml.Node) {
6267
for i, property := range node.Content {
6368
if property.Value == "image" {
6469
image := node.Content[i+1]
@@ -69,5 +74,4 @@ func (d *Tekton) findImages(refs *RefsList, node *yaml.Node) error {
6974
d.findImages(refs, property)
7075
}
7176
}
72-
return nil
7377
}

0 commit comments

Comments
 (0)