mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-17 20:47:50 +02:00
refactor: Introduced name per artifactory instance for identification
This introduced a new property per Artifactory instance: Name With this name we are able to a) identify a instance b) use the name to identify the secret (instead of a number) c) use this name for logging
This commit is contained in:
parent
13fea192c9
commit
27a9abc73b
@ -198,6 +198,7 @@ type Docker struct {
|
||||
// Artifactory server configuration
|
||||
type Artifactory struct {
|
||||
Target string `yaml:",omitempty"`
|
||||
Name string `yaml:",omitempty"`
|
||||
Username string `yaml:",omitempty"`
|
||||
|
||||
// Capture all undefined fields and should be empty after loading
|
||||
|
@ -17,7 +17,8 @@ upload target and a usernameto your `.goreleaser.yml` file:
|
||||
|
||||
```yaml
|
||||
artifactories:
|
||||
- target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}
|
||||
- name: production
|
||||
target: http://<Your-Instance>:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}
|
||||
username: goreleaser
|
||||
```
|
||||
|
||||
@ -56,10 +57,15 @@ Support variables:
|
||||
Your configured username needs to be authenticated against your Artifactory.
|
||||
|
||||
The password or API key will be stored in a environment variable.
|
||||
If you have only one Artifactory configured, you will store the secret in `ARTIFACTORY_0_SECRET`.
|
||||
The confgured name of your Artifactory instance will be used.
|
||||
With this way we support auth for multiple instances.
|
||||
This also means that the `name` per configured instance needs to be unique
|
||||
per goreleaser configuration.
|
||||
|
||||
If you have multiple instances configured, you store the password for the second instance in `ARTIFACTORY_1_SECRET`,
|
||||
for the third in `ARTIFACTORY_2_SECRET` and so on.
|
||||
The name of the environment variable will be `ARTIFACTORY_NAME_SECRET`.
|
||||
If your instance is named `production`, you need to store the secret in the
|
||||
environment variable `ARTIFACTORY_PRODUCTION_SECRET`.
|
||||
The name will be transformed to uppercase.
|
||||
|
||||
## Customization
|
||||
|
||||
@ -70,6 +76,8 @@ Of course, you can customize a lot of things:
|
||||
artifactories:
|
||||
# You can have multiple Artifactory instances.
|
||||
-
|
||||
# Unique name of your artifactory instance. Used to identify the instance
|
||||
name: production
|
||||
# URL of your Artifactory instance + path to deploy to
|
||||
target: http://artifacts.company.com:8081/artifactory/example-repo-local/{{ .ProjectName }}/{{ .Version }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}{{ .Arm }}{{ end }}
|
||||
# User that will be used for the deployment
|
||||
|
@ -58,26 +58,28 @@ func (Pipe) String() string {
|
||||
//
|
||||
// Docs: https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API#ArtifactoryRESTAPI-Example-DeployinganArtifact
|
||||
func (Pipe) Run(ctx *context.Context) error {
|
||||
instances := len(ctx.Config.Artifactories)
|
||||
if instances == 0 {
|
||||
if l := len(ctx.Config.Artifactories); l == 0 {
|
||||
return pipeline.Skip("artifactory section is not configured")
|
||||
}
|
||||
|
||||
// Check if for every instance we have a the target,
|
||||
// the username and a secret (password or api key)
|
||||
// If not, we can skip this pipeline
|
||||
for i := 0; i < instances; i++ {
|
||||
if ctx.Config.Artifactories[i].Target == "" {
|
||||
return pipeline.Skip(fmt.Sprintf("artifactory section is not configured properly (missing target in artifactory %d)", i))
|
||||
// Check requirements for every instance we have configured.
|
||||
// If not fulfilled, we can skip this pipeline
|
||||
for _, instance := range ctx.Config.Artifactories {
|
||||
if instance.Target == "" {
|
||||
return pipeline.Skip("artifactory section is not configured properly (missing target)")
|
||||
}
|
||||
|
||||
if ctx.Config.Artifactories[i].Username == "" {
|
||||
return pipeline.Skip(fmt.Sprintf("artifactory section is not configured properly (missing username in artifactory %d)", i))
|
||||
if instance.Username == "" {
|
||||
return pipeline.Skip("artifactory section is not configured properly (missing username)")
|
||||
}
|
||||
|
||||
envName := fmt.Sprintf("ARTIFACTORY_%d_SECRET", i)
|
||||
if instance.Name == "" {
|
||||
return pipeline.Skip("artifactory section is not configured properly (missing name)")
|
||||
}
|
||||
|
||||
envName := fmt.Sprintf("ARTIFACTORY_%s_SECRET", strings.ToUpper(instance.Name))
|
||||
if os.Getenv(envName) == "" {
|
||||
return pipeline.Skip(fmt.Sprintf("missing secret for artifactory %d: %s", i, ctx.Config.Artifactories[i].Target))
|
||||
return pipeline.Skip(fmt.Sprintf("missing secret for artifactory instance %s", instance.Name))
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,16 +139,15 @@ func upload(ctx *context.Context, build config.Build, target buildtarget.Target)
|
||||
}
|
||||
|
||||
// Loop over all configured Artifactory instances
|
||||
instances := len(ctx.Config.Artifactories)
|
||||
for i := 0; i < instances; i++ {
|
||||
artifactory := ctx.Config.Artifactories[i]
|
||||
secret := os.Getenv(fmt.Sprintf("ARTIFACTORY_%d_SECRET", i))
|
||||
for _, instance := range ctx.Config.Artifactories {
|
||||
secret := os.Getenv(fmt.Sprintf("ARTIFACTORY_%s_SECRET", strings.ToUpper(instance.Name)))
|
||||
|
||||
// Generate name of target
|
||||
uploadTarget, err := buildTargetName(ctx, artifactory, target)
|
||||
uploadTarget, err := buildTargetName(ctx, instance, target)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Artifactory: Error while building the target name")
|
||||
return errors.Wrap(err, "Artifactory: Error while building the target name")
|
||||
msg := "artifactory: error while building the target name"
|
||||
log.WithError(err).Error(msg)
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
||||
// The upload url to Artifactory needs the binary name
|
||||
@ -163,19 +164,22 @@ func upload(ctx *context.Context, build config.Build, target buildtarget.Target)
|
||||
}
|
||||
defer file.Close() // nolint: errcheck
|
||||
|
||||
artifact, resp, err := uploadBinaryToArtifactory(ctx, uploadTarget, artifactory.Username, secret, file)
|
||||
artifact, _, err := uploadBinaryToArtifactory(ctx, uploadTarget, instance.Username, secret, file)
|
||||
if err != nil {
|
||||
var msg string
|
||||
if resp != nil {
|
||||
msg = fmt.Sprintf("Artifactory: Upload to target %s failed (HTTP Status: %s)", uploadTarget, resp.Status)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Artifactory: Upload to target %s failed", uploadTarget)
|
||||
}
|
||||
log.WithError(err).Error(msg)
|
||||
msg := "artifactory: upload failed"
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
"instance": instance.Name,
|
||||
"username": instance.Username,
|
||||
}).Error(msg)
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
||||
log.WithField("uri", artifact.DownloadURI).WithField("target", target.PrettyString()).Info("uploaded successful")
|
||||
log.WithFields(log.Fields{
|
||||
"instance": instance.Name,
|
||||
"target": target.PrettyString(),
|
||||
"username": instance.Username,
|
||||
"uri": artifact.DownloadURI,
|
||||
}).Info("uploaded successful")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -168,10 +168,10 @@ func TestRunPipe(t *testing.T) {
|
||||
})
|
||||
|
||||
// Set secrets for artifactory instances
|
||||
os.Setenv("ARTIFACTORY_0_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_0_SECRET")
|
||||
os.Setenv("ARTIFACTORY_1_SECRET", "productionuser-apikey")
|
||||
defer os.Unsetenv("ARTIFACTORY_1_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION-US_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION-US_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION-EU_SECRET", "productionuser-apikey")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION-EU_SECRET")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
@ -188,10 +188,12 @@ func TestRunPipe(t *testing.T) {
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production-us",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
Username: "deployuser",
|
||||
},
|
||||
{
|
||||
Name: "production-eu",
|
||||
Target: fmt.Sprintf("%s/production-repo-remote/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
Username: "productionuser",
|
||||
},
|
||||
@ -237,8 +239,8 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
})
|
||||
|
||||
// Set secrets for artifactory instances
|
||||
os.Setenv("ARTIFACTORY_0_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_0_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION_SECRET")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
@ -255,6 +257,7 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: fmt.Sprintf("%s/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}", server.URL),
|
||||
Username: "deployuser",
|
||||
},
|
||||
@ -271,8 +274,8 @@ func TestRunPipe_BadCredentials(t *testing.T) {
|
||||
|
||||
func TestRunPipe_NoFile(t *testing.T) {
|
||||
// Set secrets for artifactory instances
|
||||
os.Setenv("ARTIFACTORY_0_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_0_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION_SECRET")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
@ -289,6 +292,7 @@ func TestRunPipe_NoFile(t *testing.T) {
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
},
|
||||
@ -315,8 +319,8 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Set secrets for artifactory instances
|
||||
os.Setenv("ARTIFACTORY_0_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_0_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION_SECRET")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
@ -333,6 +337,7 @@ func TestRunPipe_UnparsableTarget(t *testing.T) {
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
},
|
||||
@ -354,14 +359,10 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
assert.NoError(t, os.Mkdir(dist, 0755))
|
||||
assert.NoError(t, os.Mkdir(filepath.Join(dist, "mybin"), 0755))
|
||||
var binPath = filepath.Join(dist, "mybin")
|
||||
/*
|
||||
d1 := []byte("hello\ngo\n")
|
||||
err = ioutil.WriteFile(binPath, d1, 0666)
|
||||
assert.NoError(t, err)
|
||||
*/
|
||||
|
||||
// Set secrets for artifactory instances
|
||||
os.Setenv("ARTIFACTORY_0_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_0_SECRET")
|
||||
os.Setenv("ARTIFACTORY_PRODUCTION_SECRET", "deployuser-secret")
|
||||
defer os.Unsetenv("ARTIFACTORY_PRODUCTION_SECRET")
|
||||
|
||||
var ctx = &context.Context{
|
||||
Version: "1.0.0",
|
||||
@ -378,6 +379,7 @@ func TestRunPipe_DirUpload(t *testing.T) {
|
||||
},
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
},
|
||||
@ -404,6 +406,7 @@ func TestNoArtifactoriesWithoutTarget(t *testing.T) {
|
||||
assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Username: "deployuser",
|
||||
},
|
||||
},
|
||||
@ -414,16 +417,29 @@ func TestNoArtifactoriesWithoutUsername(t *testing.T) {
|
||||
assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
},
|
||||
},
|
||||
}))))
|
||||
}
|
||||
|
||||
func TestNoArtifactoriesWithoutName(t *testing.T) {
|
||||
assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Username: "deployuser",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
},
|
||||
},
|
||||
}))))
|
||||
}
|
||||
|
||||
func TestNoArtifactoriesWithoutSecret(t *testing.T) {
|
||||
assert.True(t, pipeline.IsSkip(Pipe{}.Run(context.New(config.Project{
|
||||
Artifactories: []config.Artifactory{
|
||||
{
|
||||
Name: "production",
|
||||
Target: "http://artifacts.company.com/example-repo-local/{{ .ProjectName }}/{{ .Os }}/{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}",
|
||||
Username: "deployuser",
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user