github.com/triarius/goreleaser@v1.12.5/internal/pipe/sign/sign_docker_test.go (about)

     1  package sign
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/triarius/goreleaser/internal/artifact"
    10  	"github.com/triarius/goreleaser/internal/gio"
    11  	"github.com/triarius/goreleaser/internal/testlib"
    12  	"github.com/triarius/goreleaser/pkg/config"
    13  	"github.com/triarius/goreleaser/pkg/context"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestDockerSignDescription(t *testing.T) {
    18  	require.NotEmpty(t, DockerPipe{}.String())
    19  }
    20  
    21  func TestDockerSignDefault(t *testing.T) {
    22  	ctx := &context.Context{
    23  		Config: config.Project{
    24  			DockerSigns: []config.Sign{{}},
    25  		},
    26  	}
    27  	err := DockerPipe{}.Default(ctx)
    28  	require.NoError(t, err)
    29  	require.Equal(t, ctx.Config.DockerSigns[0].Cmd, "cosign")
    30  	require.Equal(t, ctx.Config.DockerSigns[0].Signature, "")
    31  	require.Equal(t, ctx.Config.DockerSigns[0].Args, []string{"sign", "--key=cosign.key", "$artifact"})
    32  	require.Equal(t, ctx.Config.DockerSigns[0].Artifacts, "none")
    33  }
    34  
    35  func TestDockerSignDisabled(t *testing.T) {
    36  	ctx := context.New(config.Project{})
    37  	ctx.Config.DockerSigns = []config.Sign{
    38  		{Artifacts: "none"},
    39  	}
    40  	err := DockerPipe{}.Publish(ctx)
    41  	require.EqualError(t, err, "artifact signing is disabled")
    42  }
    43  
    44  func TestDockerSignInvalidArtifacts(t *testing.T) {
    45  	ctx := context.New(config.Project{})
    46  	ctx.Config.DockerSigns = []config.Sign{
    47  		{Artifacts: "foo"},
    48  	}
    49  	err := DockerPipe{}.Publish(ctx)
    50  	require.EqualError(t, err, "invalid list of artifacts to sign: foo")
    51  }
    52  
    53  func TestDockerSignArtifacts(t *testing.T) {
    54  	testlib.CheckPath(t, "cosign")
    55  	key := "cosign.key"
    56  	cmd := "sh"
    57  	args := []string{"-c", "echo ${artifact} > ${signature} && cosign sign --key=" + key + " --upload=false ${artifact} > ${signature}"}
    58  	password := "password"
    59  
    60  	img1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-amd64"
    61  	img2 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1-arm64v8"
    62  	man1 := "ghcr.io/caarlos0/goreleaser-docker-manifest-actions-example:1.2.1"
    63  
    64  	for name, cfg := range map[string]struct {
    65  		Signs    []config.Sign
    66  		Expected []string
    67  	}{
    68  		"no signature file": {
    69  			Expected: nil, // no sigs
    70  			Signs: []config.Sign{
    71  				{
    72  					Artifacts: "all",
    73  					Stdin:     &password,
    74  					Cmd:       "cosign",
    75  					Args:      []string{"sign", "--key=" + key, "--upload=false", "${artifact}"},
    76  				},
    77  			},
    78  		},
    79  		"only certificate": {
    80  			Expected: []string{
    81  				"ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121-amd64.pem",
    82  				"ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121-arm64v8.pem",
    83  				"ghcrio-caarlos0-goreleaser-docker-manifest-actions-example-121.pem",
    84  			},
    85  			Signs: []config.Sign{
    86  				{
    87  					Artifacts:   "all",
    88  					Stdin:       &password,
    89  					Cmd:         "cosign",
    90  					Certificate: `{{ replace (replace (replace .Env.artifact "/" "-") ":" "-") "." "" }}.pem`,
    91  					Args:        []string{"sign", "--output-certificate=${certificate}", "--key=" + key, "--upload=false", "${artifact}"},
    92  				},
    93  			},
    94  		},
    95  		"sign all": {
    96  			Expected: []string{
    97  				"all_img1.sig",
    98  				"all_img2.sig",
    99  				"all_man1.sig",
   100  			},
   101  			Signs: []config.Sign{
   102  				{
   103  					Artifacts: "all",
   104  					Stdin:     &password,
   105  					Signature: `all_${artifactID}.sig`,
   106  					Cmd:       cmd,
   107  					Args:      args,
   108  				},
   109  			},
   110  		},
   111  		"sign all filtering id": {
   112  			Expected: []string{"all_filter_by_id_img2.sig"},
   113  			Signs: []config.Sign{
   114  				{
   115  					Artifacts: "all",
   116  					IDs:       []string{"img2"},
   117  					Stdin:     &password,
   118  					Signature: "all_filter_by_id_${artifactID}.sig",
   119  					Cmd:       cmd,
   120  					Args:      args,
   121  				},
   122  			},
   123  		},
   124  		"sign images only": {
   125  			Expected: []string{
   126  				"images_img1.sig",
   127  				"images_img2.sig",
   128  			},
   129  			Signs: []config.Sign{
   130  				{
   131  					Artifacts: "images",
   132  					Stdin:     &password,
   133  					Signature: "images_${artifactID}.sig",
   134  					Cmd:       cmd,
   135  					Args:      args,
   136  				},
   137  			},
   138  		},
   139  		"sign manifests only": {
   140  			Expected: []string{"manifests_man1.sig"},
   141  			Signs: []config.Sign{
   142  				{
   143  					Artifacts: "manifests",
   144  					Stdin:     &password,
   145  					Signature: "manifests_${artifactID}.sig",
   146  					Cmd:       cmd,
   147  					Args:      args,
   148  				},
   149  			},
   150  		},
   151  		// TODO: keyless test?
   152  	} {
   153  		t.Run(name, func(t *testing.T) {
   154  			ctx := context.New(config.Project{})
   155  			ctx.Config.DockerSigns = cfg.Signs
   156  			wd, err := os.Getwd()
   157  			require.NoError(t, err)
   158  			tmp := testlib.Mktmp(t)
   159  			require.NoError(t, gio.Copy(filepath.Join(wd, "testdata/cosign/"), tmp))
   160  			ctx.Config.Dist = "dist"
   161  			require.NoError(t, os.Mkdir("dist", 0o755))
   162  
   163  			ctx.Artifacts.Add(&artifact.Artifact{
   164  				Name: img1,
   165  				Path: img1,
   166  				Type: artifact.DockerImage,
   167  				Extra: map[string]interface{}{
   168  					artifact.ExtraID: "img1",
   169  				},
   170  			})
   171  			ctx.Artifacts.Add(&artifact.Artifact{
   172  				Name: img2,
   173  				Path: img2,
   174  				Type: artifact.DockerImage,
   175  				Extra: map[string]interface{}{
   176  					artifact.ExtraID: "img2",
   177  				},
   178  			})
   179  			ctx.Artifacts.Add(&artifact.Artifact{
   180  				Name: man1,
   181  				Path: man1,
   182  				Type: artifact.DockerManifest,
   183  				Extra: map[string]interface{}{
   184  					artifact.ExtraID: "man1",
   185  				},
   186  			})
   187  
   188  			require.NoError(t, DockerPipe{}.Default(ctx))
   189  			require.NoError(t, DockerPipe{}.Publish(ctx))
   190  			var sigs []string
   191  			for _, sig := range ctx.Artifacts.Filter(
   192  				artifact.Or(
   193  					artifact.ByType(artifact.Signature),
   194  					artifact.ByType(artifact.Certificate),
   195  				),
   196  			).List() {
   197  				sigs = append(sigs, sig.Name)
   198  				require.Truef(t, strings.HasPrefix(sig.Path, ctx.Config.Dist), "signature %q is not in dist dir %q", sig.Path, ctx.Config.Dist)
   199  			}
   200  			require.Equal(t, cfg.Expected, sigs)
   201  		})
   202  	}
   203  }
   204  
   205  func TestDockerSkip(t *testing.T) {
   206  	t.Run("skip", func(t *testing.T) {
   207  		require.True(t, DockerPipe{}.Skip(context.New(config.Project{})))
   208  	})
   209  
   210  	t.Run("skip sign", func(t *testing.T) {
   211  		ctx := context.New(config.Project{})
   212  		ctx.SkipSign = true
   213  		require.True(t, DockerPipe{}.Skip(ctx))
   214  	})
   215  
   216  	t.Run("dont skip", func(t *testing.T) {
   217  		ctx := context.New(config.Project{
   218  			DockerSigns: []config.Sign{
   219  				{},
   220  			},
   221  		})
   222  		require.False(t, DockerPipe{}.Skip(ctx))
   223  	})
   224  }