Skip to content

Commit feb90fe

Browse files
authored
New input skip_push_if_tag_exists (#472)
1 parent 55c76ae commit feb90fe

File tree

1 file changed

+62
-12
lines changed

1 file changed

+62
-12
lines changed

cmd/drone-ecr/main.go

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ import (
2222
docker "github.com/drone-plugins/drone-docker"
2323
)
2424

25+
type ecrAPI interface {
26+
DescribeImages(*ecr.DescribeImagesInput) (*ecr.DescribeImagesOutput, error)
27+
}
28+
2529
const defaultRegion = "us-east-1"
2630

2731
func main() {
@@ -31,18 +35,19 @@ func main() {
3135
}
3236

3337
var (
34-
repo = getenv("PLUGIN_REPO")
35-
registry = getenv("PLUGIN_REGISTRY")
36-
region = getenv("PLUGIN_REGION", "ECR_REGION", "AWS_REGION")
37-
key = getenv("PLUGIN_ACCESS_KEY", "ECR_ACCESS_KEY", "AWS_ACCESS_KEY_ID")
38-
secret = getenv("PLUGIN_SECRET_KEY", "ECR_SECRET_KEY", "AWS_SECRET_ACCESS_KEY")
39-
create = parseBoolOrDefault(false, getenv("PLUGIN_CREATE_REPOSITORY", "ECR_CREATE_REPOSITORY"))
40-
lifecyclePolicy = getenv("PLUGIN_LIFECYCLE_POLICY")
41-
repositoryPolicy = getenv("PLUGIN_REPOSITORY_POLICY")
42-
assumeRole = getenv("PLUGIN_ASSUME_ROLE")
43-
externalId = getenv("PLUGIN_EXTERNAL_ID")
44-
scanOnPush = parseBoolOrDefault(false, getenv("PLUGIN_SCAN_ON_PUSH"))
45-
idToken = os.Getenv("PLUGIN_OIDC_TOKEN_ID")
38+
repo = getenv("PLUGIN_REPO")
39+
registry = getenv("PLUGIN_REGISTRY")
40+
region = getenv("PLUGIN_REGION", "ECR_REGION", "AWS_REGION")
41+
key = getenv("PLUGIN_ACCESS_KEY", "ECR_ACCESS_KEY", "AWS_ACCESS_KEY_ID")
42+
secret = getenv("PLUGIN_SECRET_KEY", "ECR_SECRET_KEY", "AWS_SECRET_ACCESS_KEY")
43+
create = parseBoolOrDefault(false, getenv("PLUGIN_CREATE_REPOSITORY", "ECR_CREATE_REPOSITORY"))
44+
lifecyclePolicy = getenv("PLUGIN_LIFECYCLE_POLICY")
45+
repositoryPolicy = getenv("PLUGIN_REPOSITORY_POLICY")
46+
assumeRole = getenv("PLUGIN_ASSUME_ROLE")
47+
externalId = getenv("PLUGIN_EXTERNAL_ID")
48+
scanOnPush = parseBoolOrDefault(false, getenv("PLUGIN_SCAN_ON_PUSH"))
49+
idToken = os.Getenv("PLUGIN_OIDC_TOKEN_ID")
50+
skipPushIfTagExists = parseBoolOrDefault(false, getenv("PLUGIN_SKIP_PUSH_IF_TAG_EXISTS"))
4651
)
4752

4853
// set the region
@@ -114,6 +119,34 @@ func main() {
114119
os.Setenv("DOCKER_PASSWORD", password)
115120
os.Setenv("PLUGIN_REGISTRY_TYPE", "ECR")
116121

122+
// Skip if tag already exits for both mutable and immutable repos
123+
if skipPushIfTagExists {
124+
tagInput := getenv("PLUGIN_TAG", "PLUGIN_TAGS")
125+
var tags []string
126+
if tagInput == "" {
127+
tags = []string{"latest"}
128+
} else {
129+
for _, t := range strings.Split(tagInput, ",") {
130+
trimmed := strings.TrimSpace(t)
131+
if trimmed != "" {
132+
tags = append(tags, trimmed)
133+
}
134+
}
135+
}
136+
137+
repositoryName := trimHostname(repo, registry)
138+
for _, t := range tags {
139+
exists, err := tagExists(svc, repositoryName, t)
140+
if err != nil {
141+
logrus.Fatalf("Error checking if image exists for tag %s: %v", t, err)
142+
}
143+
if exists {
144+
logrus.Infof("%s:%s: Image tag exists. Skipping push.", repo, t)
145+
os.Exit(0)
146+
}
147+
}
148+
}
149+
117150
// invoke the base docker plugin binary
118151
cmd := exec.Command(docker.GetDroneDockerExecCmd())
119152
cmd.Stdout = os.Stdout
@@ -249,3 +282,20 @@ func getECRClient(sess *session.Session, role string, externalId string, idToken
249282
})
250283
}
251284
}
285+
286+
func tagExists(svc ecrAPI, repository, tag string) (bool, error) {
287+
input := &ecr.DescribeImagesInput{
288+
RepositoryName: aws.String(repository),
289+
ImageIds: []*ecr.ImageIdentifier{
290+
{ImageTag: aws.String(tag)},
291+
},
292+
}
293+
output, err := svc.DescribeImages(input)
294+
if err != nil {
295+
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == "ImageNotFoundException" {
296+
return false, nil
297+
}
298+
return false, err
299+
}
300+
return len(output.ImageDetails) > 0, nil
301+
}

0 commit comments

Comments
 (0)