commit
46aa2877ab
@ -19,6 +19,7 @@ import (
|
|||||||
_ "github.com/moby/buildkit/client/connhelper/dockercontainer" // import the container connection driver
|
_ "github.com/moby/buildkit/client/connhelper/dockercontainer" // import the container connection driver
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
|
"github.com/moby/buildkit/session"
|
||||||
|
|
||||||
// docker output
|
// docker output
|
||||||
"dagger.io/go/pkg/buildkitd"
|
"dagger.io/go/pkg/buildkitd"
|
||||||
@ -101,9 +102,13 @@ func (c *Client) buildfn(ctx context.Context, deployment *Deployment, fn ClientD
|
|||||||
localdirs[label] = abs
|
localdirs[label] = abs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildkit auth provider (registry)
|
||||||
|
auth := newRegistryAuthProvider()
|
||||||
|
|
||||||
// Setup solve options
|
// Setup solve options
|
||||||
opts := bk.SolveOpt{
|
opts := bk.SolveOpt{
|
||||||
LocalDirs: localdirs,
|
LocalDirs: localdirs,
|
||||||
|
Session: []session.Attachable{auth},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call buildkit solver
|
// Call buildkit solver
|
||||||
@ -113,7 +118,7 @@ func (c *Client) buildfn(ctx context.Context, deployment *Deployment, fn ClientD
|
|||||||
Msg("spawning buildkit job")
|
Msg("spawning buildkit job")
|
||||||
|
|
||||||
resp, err := c.c.Build(ctx, opts, "", func(ctx context.Context, gw bkgw.Client) (*bkgw.Result, error) {
|
resp, err := c.c.Build(ctx, opts, "", func(ctx context.Context, gw bkgw.Client) (*bkgw.Result, error) {
|
||||||
s := NewSolver(c.c, gw, ch, c.noCache)
|
s := NewSolver(c.c, gw, ch, auth, c.noCache)
|
||||||
|
|
||||||
lg.Debug().Msg("loading configuration")
|
lg.Debug().Msg("loading configuration")
|
||||||
if err := deployment.LoadPlan(ctx, s); err != nil {
|
if err := deployment.LoadPlan(ctx, s); err != nil {
|
||||||
|
@ -197,6 +197,8 @@ func (p *Pipeline) doOp(ctx context.Context, op *compiler.Value, st llb.State) (
|
|||||||
return p.Exec(ctx, op, st)
|
return p.Exec(ctx, op, st)
|
||||||
case "export":
|
case "export":
|
||||||
return p.Export(ctx, op, st)
|
return p.Export(ctx, op, st)
|
||||||
|
case "docker-login":
|
||||||
|
return p.DockerLogin(ctx, op, st)
|
||||||
case "fetch-container":
|
case "fetch-container":
|
||||||
return p.FetchContainer(ctx, op, st)
|
return p.FetchContainer(ctx, op, st)
|
||||||
case "push-container":
|
case "push-container":
|
||||||
@ -559,6 +561,32 @@ func (p *Pipeline) Load(ctx context.Context, op *compiler.Value, st llb.State) (
|
|||||||
return from.State(), nil
|
return from.State(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pipeline) DockerLogin(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||||
|
username, err := op.Lookup("username").String()
|
||||||
|
if err != nil {
|
||||||
|
return st, err
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, err := op.Lookup("secret").String()
|
||||||
|
if err != nil {
|
||||||
|
return st, err
|
||||||
|
}
|
||||||
|
|
||||||
|
target, err := op.Lookup("target").String()
|
||||||
|
if err != nil {
|
||||||
|
return st, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.s.auth.AddCredentials(target, username, secret)
|
||||||
|
log.
|
||||||
|
Ctx(ctx).
|
||||||
|
Debug().
|
||||||
|
Str("target", target).
|
||||||
|
Msg("docker login to registry")
|
||||||
|
|
||||||
|
return st, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pipeline) FetchContainer(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
func (p *Pipeline) FetchContainer(ctx context.Context, op *compiler.Value, st llb.State) (llb.State, error) {
|
||||||
rawRef, err := op.Lookup("ref").String()
|
rawRef, err := op.Lookup("ref").String()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
86
dagger/registryauth.go
Normal file
86
dagger/registryauth.go
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
package dagger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
bkauth "github.com/moby/buildkit/session/auth"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// registryAuthProvider is a buildkit provider for registry authentication
|
||||||
|
// Adapted from: https://github.com/moby/buildkit/blob/master/session/auth/authprovider/authprovider.go
|
||||||
|
type registryAuthProvider struct {
|
||||||
|
credentials map[string]*bkauth.CredentialsResponse
|
||||||
|
m sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRegistryAuthProvider() *registryAuthProvider {
|
||||||
|
return ®istryAuthProvider{
|
||||||
|
credentials: map[string]*bkauth.CredentialsResponse{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) AddCredentials(target, username, secret string) {
|
||||||
|
a.m.Lock()
|
||||||
|
defer a.m.Unlock()
|
||||||
|
|
||||||
|
a.credentials[target] = &bkauth.CredentialsResponse{
|
||||||
|
Username: username,
|
||||||
|
Secret: secret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) Register(server *grpc.Server) {
|
||||||
|
bkauth.RegisterAuthServer(server, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) Credentials(ctx context.Context, req *bkauth.CredentialsRequest) (*bkauth.CredentialsResponse, error) {
|
||||||
|
reqURL, err := parseAuthHost(req.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.m.RLock()
|
||||||
|
defer a.m.RUnlock()
|
||||||
|
|
||||||
|
for authHost, auth := range a.credentials {
|
||||||
|
u, err := parseAuthHost(authHost)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Host == reqURL.Host {
|
||||||
|
return auth, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &bkauth.CredentialsResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAuthHost(host string) (*url.URL, error) {
|
||||||
|
if host == "registry-1.docker.io" {
|
||||||
|
host = "https://index.docker.io/v1/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasPrefix(host, "http://") && !strings.HasPrefix(host, "https://") {
|
||||||
|
host = "https://" + host
|
||||||
|
}
|
||||||
|
return url.Parse(host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) FetchToken(ctx context.Context, req *bkauth.FetchTokenRequest) (rr *bkauth.FetchTokenResponse, err error) {
|
||||||
|
return nil, status.Errorf(codes.Unavailable, "client side tokens not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) GetTokenAuthority(ctx context.Context, req *bkauth.GetTokenAuthorityRequest) (*bkauth.GetTokenAuthorityResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unavailable, "client side tokens not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *registryAuthProvider) VerifyTokenAuthority(ctx context.Context, req *bkauth.VerifyTokenAuthorityRequest) (*bkauth.VerifyTokenAuthorityResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unavailable, "client side tokens not implemented")
|
||||||
|
}
|
@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
|
"github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
|
||||||
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
bkgw "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/session/auth/authprovider"
|
|
||||||
bkpb "github.com/moby/buildkit/solver/pb"
|
bkpb "github.com/moby/buildkit/solver/pb"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@ -23,14 +22,16 @@ type Solver struct {
|
|||||||
events chan *bk.SolveStatus
|
events chan *bk.SolveStatus
|
||||||
control *bk.Client
|
control *bk.Client
|
||||||
gw bkgw.Client
|
gw bkgw.Client
|
||||||
|
auth *registryAuthProvider
|
||||||
noCache bool
|
noCache bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSolver(control *bk.Client, gw bkgw.Client, events chan *bk.SolveStatus, noCache bool) Solver {
|
func NewSolver(control *bk.Client, gw bkgw.Client, events chan *bk.SolveStatus, auth *registryAuthProvider, noCache bool) Solver {
|
||||||
return Solver{
|
return Solver{
|
||||||
events: events,
|
events: events,
|
||||||
control: control,
|
control: control,
|
||||||
gw: gw,
|
gw: gw,
|
||||||
|
auth: auth,
|
||||||
noCache: noCache,
|
noCache: noCache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,9 +149,7 @@ func (s Solver) Export(ctx context.Context, st llb.State, img *dockerfile2llb.Im
|
|||||||
|
|
||||||
opts := bk.SolveOpt{
|
opts := bk.SolveOpt{
|
||||||
Exports: []bk.ExportEntry{output},
|
Exports: []bk.ExportEntry{output},
|
||||||
Session: []session.Attachable{
|
Session: []session.Attachable{s.auth},
|
||||||
authprovider.NewDockerAuthProvider(log.Ctx(ctx)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan *bk.SolveStatus)
|
ch := make(chan *bk.SolveStatus)
|
||||||
|
@ -17,12 +17,9 @@ import (
|
|||||||
awsConfig: aws.#Config
|
awsConfig: aws.#Config
|
||||||
buildArgs: [string]: string
|
buildArgs: [string]: string
|
||||||
|
|
||||||
pushTarget: "\(repository):\(tag)"
|
|
||||||
|
|
||||||
// Use these credentials to push
|
// Use these credentials to push
|
||||||
ecrCreds: ecr.#Credentials & {
|
ecrCreds: ecr.#Credentials & {
|
||||||
config: awsConfig
|
config: awsConfig
|
||||||
target: pushTarget
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref: {
|
ref: {
|
||||||
@ -37,9 +34,15 @@ import (
|
|||||||
}
|
}
|
||||||
buildArg: buildArgs
|
buildArg: buildArgs
|
||||||
},
|
},
|
||||||
|
// Login to Registry
|
||||||
|
op.#DockerLogin & {
|
||||||
|
target: repository
|
||||||
|
username: ecrCreds.username
|
||||||
|
secret: ecrCreds.secret
|
||||||
|
},
|
||||||
// Push the image to the registry
|
// Push the image to the registry
|
||||||
op.#PushContainer & {
|
op.#PushContainer & {
|
||||||
ref: pushTarget
|
ref: "\(repository):\(tag)"
|
||||||
},
|
},
|
||||||
op.#Export & {
|
op.#Export & {
|
||||||
source: "/dagger/image_ref"
|
source: "/dagger/image_ref"
|
||||||
|
1
go.mod
1
go.mod
@ -29,6 +29,7 @@ require (
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
|
||||||
|
google.golang.org/grpc v1.29.1
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc
|
gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
1
go.sum
1
go.sum
@ -305,7 +305,6 @@ github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r
|
|||||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v17.12.0-ce-rc1.0.20200730172259-9f28837c1d93+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible h1:J2OhsbfqoBRRT048iD/tqXBvEQWQATQ8vew6LqQmDSU=
|
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible h1:J2OhsbfqoBRRT048iD/tqXBvEQWQATQ8vew6LqQmDSU=
|
||||||
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
github.com/docker/docker v20.10.0-beta1.0.20201110211921-af34b94a78a1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
|
|
||||||
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
|
@ -7,30 +7,21 @@ import (
|
|||||||
|
|
||||||
// Credentials retriever for ECR
|
// Credentials retriever for ECR
|
||||||
#Credentials: {
|
#Credentials: {
|
||||||
|
|
||||||
// AWS Config
|
// AWS Config
|
||||||
config: aws.#Config
|
config: aws.#Config
|
||||||
|
|
||||||
// Target is the ECR image
|
|
||||||
target: string
|
|
||||||
|
|
||||||
out: dagger.#Secret
|
out: dagger.#Secret
|
||||||
|
|
||||||
// ECR credentials
|
// ECR credentials
|
||||||
credentials: dagger.#RegistryCredentials & {
|
|
||||||
username: "AWS"
|
username: "AWS"
|
||||||
secret: out
|
secret: out
|
||||||
}
|
|
||||||
|
|
||||||
aws.#Script & {
|
aws.#Script & {
|
||||||
|
always: true
|
||||||
"config": config
|
"config": config
|
||||||
export: "/out"
|
export: "/out"
|
||||||
code: """
|
code: """
|
||||||
aws ecr get-login-password > /out
|
aws ecr get-login-password > /out
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authentication for ECR Registries
|
|
||||||
auth: dagger.#RegistryAuth
|
|
||||||
auth: "\(target)": credentials
|
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,14 @@ package op
|
|||||||
mount: [string]: "tmpfs" | "cache" | {from: _, path: string | *"/"}
|
mount: [string]: "tmpfs" | "cache" | {from: _, path: string | *"/"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#DockerLogin: {
|
||||||
|
do: "docker-login"
|
||||||
|
target: string | *"https://index.docker.io/v1/"
|
||||||
|
username: string
|
||||||
|
// FIXME: should be a #Secret (circular import)
|
||||||
|
secret: string | bytes
|
||||||
|
}
|
||||||
|
|
||||||
#FetchContainer: {
|
#FetchContainer: {
|
||||||
do: "fetch-container"
|
do: "fetch-container"
|
||||||
ref: string
|
ref: string
|
||||||
|
@ -84,6 +84,11 @@ setup() {
|
|||||||
@test "op.#PushContainer" {
|
@test "op.#PushContainer" {
|
||||||
skip_unless_secrets_available "$TESTDIR"/ops/push-container/inputs.yaml
|
skip_unless_secrets_available "$TESTDIR"/ops/push-container/inputs.yaml
|
||||||
|
|
||||||
|
# ensure the tests fail without credentials
|
||||||
|
run "$DAGGER" compute "$TESTDIR"/ops/push-container/valid
|
||||||
|
assert_failure
|
||||||
|
|
||||||
|
# check that they succeed with the credentials
|
||||||
run "$DAGGER" compute --input-yaml "$TESTDIR"/ops/push-container/inputs.yaml "$TESTDIR"/ops/push-container
|
run "$DAGGER" compute --input-yaml "$TESTDIR"/ops/push-container/inputs.yaml "$TESTDIR"/ops/push-container
|
||||||
assert_success
|
assert_success
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
registry:
|
registry:
|
||||||
username: ENC[AES256_GCM,data:8AH6p9WHidanCA==,iv:ezThCQJv+bVBf8SdfSa2HFoP+eu6IZMPl5xvMOGDcps=,tag:mzR7xTKeQNDvkyd2Dm3AKw==,type:str]
|
username: ENC[AES256_GCM,data:8AH6p9WHidanCA==,iv:ezThCQJv+bVBf8SdfSa2HFoP+eu6IZMPl5xvMOGDcps=,tag:mzR7xTKeQNDvkyd2Dm3AKw==,type:str]
|
||||||
token: ENC[AES256_GCM,data:68d31b3EfnQJofIt6j+iBCtDyLOBWjFqvVmejyDjIOh8oBXP,iv:PMghC2nd7jqAzrQzm/PW1YdbE0VAbEBkK0/Ri1WwduI=,tag:0JH4WbcJHvgzF4VIK4deBg==,type:str]
|
secret: ENC[AES256_GCM,data:GtuaBAhFBw2JFaeuOm6mUr3m1j5fvCJjcWAzjsdU2xASFxwO,iv:YAXcRzBoemmef5PBdAOBa5acNPo4BoKH7Ngud/CWYfA=,tag:MCCUCOSutjRCI92raYrxdg==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
azure_kv: []
|
azure_kv: []
|
||||||
hc_vault: []
|
hc_vault: []
|
||||||
lastmodified: '2021-03-18T22:59:59Z'
|
age: []
|
||||||
mac: ENC[AES256_GCM,data:3++nHOAJaYFCEuUXim4/gOsG1ZVWt8Ab88qaqHM6jpCA2gLSyADWpB5iQfU9bM7Sq3PgCcWd5+mDHxl5Q8r9fiozrS025OLtsn7qQQQ84WaiFz9Y4Trsbe4EJXNpxYDXjLZEkEtkKs4/Dl+y2Ey3nVyIWKZEX9cPogJ64zfFS9Q=,iv:jvSwxJ8Of2Nfp1ijKItOraDO8aS6aGHQKFY61kF8JS8=,tag:I+AWPIZsPeXU30zxbgq2eQ==,type:str]
|
lastmodified: "2021-04-27T00:59:33Z"
|
||||||
|
mac: ENC[AES256_GCM,data:qk+oo4m5OpfuQ+R3pZUuvn+gqAk15OAJzOULrlYqt1FIDRk/Q5ah5QpIbVxeP1EDVyuY/V/E0ZngRlSV7Dyx6Cp/moMd8AFBHNgnTB+Lq+NmZ9HR1QMOxpbMpJmUGn7MqQ1Ys4wy0p2q2Y2+TuUpKwmRGJbGVYEVmqvV5OT3jhc=,iv:QsUFa2GVzy6iqqLXRz8HascQZPIIzKBhxHdlabov02k=,tag:7lk63FeXsOlTCgfmWd7zrg==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: '2021-03-18T22:59:59Z'
|
- created_at: "2021-03-18T22:59:59Z"
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN PGP MESSAGE-----
|
-----BEGIN PGP MESSAGE-----
|
||||||
|
|
||||||
@ -30,4 +31,4 @@ sops:
|
|||||||
-----END PGP MESSAGE-----
|
-----END PGP MESSAGE-----
|
||||||
fp: 6CB37404020B5F0A0B41B5BB225EBAB0B936AC65
|
fp: 6CB37404020B5F0A0B41B5BB225EBAB0B936AC65
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.6.1
|
version: 3.7.1
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"dagger.io/dagger"
|
||||||
"dagger.io/dagger/op"
|
"dagger.io/dagger/op"
|
||||||
"dagger.io/alpine"
|
"dagger.io/alpine"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
registry: {
|
||||||
|
username: string
|
||||||
|
secret: dagger.#Secret
|
||||||
|
}
|
||||||
|
|
||||||
TestPushContainer: {
|
TestPushContainer: {
|
||||||
// Generate a random number
|
// Generate a random number
|
||||||
random: {
|
random: {
|
||||||
@ -24,6 +30,9 @@ TestPushContainer: {
|
|||||||
push: {
|
push: {
|
||||||
ref: "daggerio/ci-test:\(random)"
|
ref: "daggerio/ci-test:\(random)"
|
||||||
#up: [
|
#up: [
|
||||||
|
op.#DockerLogin & {
|
||||||
|
registry
|
||||||
|
},
|
||||||
op.#WriteFile & {
|
op.#WriteFile & {
|
||||||
content: random
|
content: random
|
||||||
dest: "/rand"
|
dest: "/rand"
|
||||||
|
Reference in New Issue
Block a user