mirror of
https://github.com/harness-community/drone-nexus-publish.git
synced 2026-06-04 10:15:01 +08:00
moving all code to plugin.go and tests to plugin_test.go
This commit is contained in:
-55
@@ -1,55 +0,0 @@
|
||||
# Blue Oak Model License
|
||||
|
||||
Version 1.0.0
|
||||
|
||||
## Purpose
|
||||
|
||||
This license gives everyone as much permission to work with
|
||||
this software as possible, while protecting contributors
|
||||
from liability.
|
||||
|
||||
## Acceptance
|
||||
|
||||
In order to receive this license, you must agree to its
|
||||
rules. The rules of this license are both obligations
|
||||
under that agreement and conditions to your license.
|
||||
You must not do anything with this software that triggers
|
||||
a rule that you cannot or will not follow.
|
||||
|
||||
## Copyright
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe that contributor's
|
||||
copyright in it.
|
||||
|
||||
## Notices
|
||||
|
||||
You must ensure that everyone who gets a copy of
|
||||
any part of this software from you, with or without
|
||||
changes, also gets the text of this license or a link to
|
||||
<https://blueoakcouncil.org/license/1.0.0>.
|
||||
|
||||
## Excuse
|
||||
|
||||
If anyone notifies you in writing that you have not
|
||||
complied with [Notices](#notices), you can keep your
|
||||
license by taking all practical steps to comply within 30
|
||||
days after the notice. If you do not do so, your license
|
||||
ends immediately.
|
||||
|
||||
## Patent
|
||||
|
||||
Each contributor licenses you to do everything with this
|
||||
software that would otherwise infringe any patent claims
|
||||
they can license or become able to license.
|
||||
|
||||
## Reliability
|
||||
|
||||
No contributor can revoke this license.
|
||||
|
||||
## No Liability
|
||||
|
||||
***As far as the law allows, this software comes as is,
|
||||
without any warranty or condition, and no contributor
|
||||
will be liable to anyone for any damages related to this
|
||||
software or this license, under any kind of legal claim.***
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM alpine:3.6 as alpine
|
||||
FROM alpine:3.20 as alpine
|
||||
RUN apk add -U --no-cache ca-certificates
|
||||
|
||||
FROM alpine:3.6
|
||||
FROM alpine:3.20
|
||||
ENV GODEBUG netdns=go
|
||||
|
||||
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
|
||||
@@ -1,445 +0,0 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type HttpClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
type NexusPlugin struct {
|
||||
InputArgs *Args
|
||||
IsMultiFileUpload bool
|
||||
PluginProcessingInfo
|
||||
NexusPluginResponse
|
||||
HttpClient HttpClient
|
||||
}
|
||||
|
||||
type PluginProcessingInfo struct {
|
||||
UserName string
|
||||
Password string
|
||||
ServerUrl string
|
||||
Version string
|
||||
Format string
|
||||
Repository string
|
||||
GroupId string
|
||||
Artifacts []Artifact
|
||||
}
|
||||
|
||||
type NexusPluginResponse struct {
|
||||
Failed []FailedArtifact `json:"failed"`
|
||||
}
|
||||
|
||||
type FailedArtifact struct {
|
||||
File string `json:"file"`
|
||||
ArtifactId string `json:"artifactId"`
|
||||
Err string `json:"err"`
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) Run() error {
|
||||
LogPrintln(n, "Starting Nexus Plugin Run")
|
||||
|
||||
if n.HttpClient == nil {
|
||||
n.HttpClient = &http.Client{}
|
||||
}
|
||||
|
||||
for _, artifact := range n.Artifacts {
|
||||
filePath := artifact.File
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("could not open file: %v", err))
|
||||
continue
|
||||
}
|
||||
|
||||
if n.Version == "nexus2" {
|
||||
artifactURL := n.prepareNexus2ArtifactURL(artifact)
|
||||
if err := n.uploadFileNexus2(artifactURL, file, filePath); err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("upload failed: %v", err))
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else if n.Version == "nexus3" {
|
||||
if err := n.uploadFileNexus3(artifact, filePath); err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("upload failed: %v", err))
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("Successfully uploaded artifact:", filePath)
|
||||
}
|
||||
|
||||
if len(n.Failed) > 0 {
|
||||
return GetNewError("NexusPlugin Error in Run: some artifacts failed to upload")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) WriteOutputVariables() error {
|
||||
|
||||
type EnvKvPair struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
var kvPairs []EnvKvPair
|
||||
|
||||
if len(n.Failed) == 0 {
|
||||
LogPrintln(n, "All artifacts uploaded successfully")
|
||||
kvPairs = append(kvPairs, EnvKvPair{Key: "UPLOAD_STATUS", Value: "Success"})
|
||||
} else {
|
||||
kvPairs = append(kvPairs, EnvKvPair{Key: "UPLOAD_STATUS", Value: n.Failed})
|
||||
}
|
||||
|
||||
var retErr error = nil
|
||||
|
||||
for _, kvPair := range kvPairs {
|
||||
err := WriteEnvVariableAsString(kvPair.Key, kvPair.Value)
|
||||
if err != nil {
|
||||
retErr = err
|
||||
}
|
||||
}
|
||||
|
||||
return retErr
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) Init(args *Args) error {
|
||||
n.InputArgs = args
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) SetBuildRoot(buildRootPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DeInit() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) ValidateAndProcessArgs(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin BuildAndValidateArgs")
|
||||
|
||||
err := n.DetermineIsMultiFileUpload(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if n.IsMultiFileUpload {
|
||||
err = n.IsMultiFileUploadArgsOk(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = n.IsSingleFileUploadArgsOk(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DetermineIsMultiFileUpload(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin DetermineIsMultiFileUpload")
|
||||
|
||||
switch {
|
||||
case args.Attributes != "" && args.Artifact == "":
|
||||
n.IsMultiFileUpload = false
|
||||
case args.Artifact != "" && args.Attributes == "":
|
||||
n.IsMultiFileUpload = true
|
||||
case args.Attributes == "" && args.Artifact == "":
|
||||
return GetNewError("Error in DetermineCompatibilityMode: both 'Attributes' and 'Artifact' cannot be empty")
|
||||
default:
|
||||
return GetNewError("Error in DetermineCompatibilityMode: both 'Attributes' and 'Artifact' provided, which is ambiguous")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsMultiFileUploadArgsOk(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin IsMultiFileUploadArgsOk")
|
||||
|
||||
requiredArgs := map[string]string{
|
||||
"username": args.Username,
|
||||
"password": args.Password,
|
||||
"protocol": args.Protocol,
|
||||
"nexusUrl": args.ServerUrl,
|
||||
"nexusVersion": args.NexusVersion,
|
||||
"repository": args.Repository,
|
||||
"groupId": args.GroupId,
|
||||
"format": args.Format,
|
||||
}
|
||||
|
||||
for field, value := range requiredArgs {
|
||||
if value == "" {
|
||||
return GetNewError("Error in IsMultiFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
|
||||
n.UserName = args.Username
|
||||
n.Password = args.Password
|
||||
n.Repository = args.Repository
|
||||
n.ServerUrl = args.Protocol + "://" + args.ServerUrl
|
||||
n.GroupId = args.GroupId
|
||||
n.Version = args.NexusVersion
|
||||
n.Format = args.Format
|
||||
|
||||
// Unmarshalling YAML artifact data
|
||||
var artifacts []Artifact
|
||||
if err := yaml.Unmarshal([]byte(args.Artifact), &artifacts); err != nil {
|
||||
return GetNewError("Error in IsMultiFileUploadArgsOk: Error decoding YAML: " + err.Error())
|
||||
}
|
||||
|
||||
var filteredArtifacts []Artifact
|
||||
for _, artifact := range artifacts {
|
||||
missingFields := []string{}
|
||||
if artifact.ArtifactId == "" {
|
||||
missingFields = append(missingFields, "ArtifactId")
|
||||
}
|
||||
if artifact.File == "" {
|
||||
missingFields = append(missingFields, "File")
|
||||
}
|
||||
if artifact.Type == "" {
|
||||
missingFields = append(missingFields, "Type")
|
||||
}
|
||||
if artifact.Version == "" {
|
||||
missingFields = append(missingFields, "Version")
|
||||
}
|
||||
if artifact.GroupId == "" {
|
||||
artifact.GroupId = args.GroupId
|
||||
}
|
||||
if len(missingFields) > 0 {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("Missing fields: %s", strings.Join(missingFields, ", ")))
|
||||
} else {
|
||||
// Add to filtered list if all fields are valid
|
||||
filteredArtifacts = append(filteredArtifacts, artifact)
|
||||
}
|
||||
}
|
||||
|
||||
n.Artifacts = filteredArtifacts
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsSingleFileUploadArgsOk(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin IsSingleFileUploadArgsOk")
|
||||
|
||||
requiredArgs := map[string]string{
|
||||
"Username": args.Username,
|
||||
"Password": args.Password,
|
||||
"ServerUrl": args.ServerUrl,
|
||||
"Filename": args.Filename,
|
||||
"Format": args.Format,
|
||||
"Repository": args.Repository,
|
||||
}
|
||||
|
||||
for field, value := range requiredArgs {
|
||||
if value == "" {
|
||||
return GetNewError("Error in IsSingleFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
|
||||
requiredFields := []string{"CgroupId", "Cversion", "Aextension", "Aclassifier"}
|
||||
values := make(map[string]string)
|
||||
|
||||
pattern := regexp.MustCompile(`-(CgroupId|CartifactId|Cversion|Aextension|Aclassifier)=(\S+)`)
|
||||
matches := pattern.FindAllStringSubmatch(args.Attributes, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
if len(match) == 3 {
|
||||
values[match[1]] = match[2]
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all required fields are present
|
||||
for _, field := range requiredFields {
|
||||
if values[field] == "" {
|
||||
return GetNewError("Error in IsSingleFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
n.UserName = args.Username
|
||||
n.Password = args.Password
|
||||
n.Repository = args.Repository
|
||||
n.ServerUrl = args.ServerUrl
|
||||
n.Format = args.Format
|
||||
n.GroupId = values["CgroupId"]
|
||||
n.Version = "nexus3"
|
||||
n.Artifacts = []Artifact{
|
||||
{
|
||||
File: args.Filename,
|
||||
Classifier: values["Aclassifier"],
|
||||
ArtifactId: values["CartifactId"],
|
||||
Type: values["Aextension"],
|
||||
Version: values["Cversion"],
|
||||
GroupId: values["CgroupId"],
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DoPostArgsValidationSetup(args Args) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) PersistResults() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsQuiet() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) InspectProcessArgs(argNamesList []string) (map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func GetNewNexusPlugin() NexusPlugin {
|
||||
return NexusPlugin{}
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) prepareNexus2ArtifactURL(artifact Artifact) string {
|
||||
switch n.Format {
|
||||
case "maven2":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s/%s/%s-%s.%s",
|
||||
n.ServerUrl, n.Repository, artifact.GroupId, artifact.ArtifactId, artifact.Version,
|
||||
artifact.ArtifactId, artifact.Version, artifact.Type)
|
||||
|
||||
case "yum":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s",
|
||||
n.ServerUrl, n.Repository, artifact.ArtifactId, artifact.Version)
|
||||
|
||||
case "raw":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s.%s",
|
||||
n.ServerUrl, n.Repository, artifact.GroupId, artifact.ArtifactId, artifact.Type)
|
||||
|
||||
default:
|
||||
LogPrintln(n, "Unsupported format for direct upload:", n.Format)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) uploadFileNexus2(url string, content io.Reader, filePath string) error {
|
||||
req, err := http.NewRequest("PUT", url, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(n.UserName, n.Password)
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
|
||||
resp, err := n.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
fmt.Println("File upload failed status ", resp.StatusCode)
|
||||
return fmt.Errorf("Upload failed with status %d", resp.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) uploadFileNexus3(artifact Artifact, filePath string) error {
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
var url string
|
||||
var assetFieldName string
|
||||
|
||||
switch n.Format {
|
||||
case "maven2":
|
||||
_ = writer.WriteField("maven2.groupId", artifact.GroupId)
|
||||
_ = writer.WriteField("maven2.artifactId", artifact.ArtifactId)
|
||||
_ = writer.WriteField("maven2.version", artifact.Version)
|
||||
assetFieldName = "maven2.asset1"
|
||||
_ = writer.WriteField("maven2.asset1.extension", artifact.Type)
|
||||
|
||||
case "raw":
|
||||
_ = writer.WriteField("raw.directory", artifact.GroupId)
|
||||
assetFieldName = "raw.asset1"
|
||||
_ = writer.WriteField("raw.asset1.filename", fmt.Sprintf("%s.%s", artifact.ArtifactId, artifact.Type))
|
||||
|
||||
default:
|
||||
assetFieldName = fmt.Sprintf("%s.asset", n.Format)
|
||||
}
|
||||
|
||||
fileWriter, err := writer.CreateFormFile(assetFieldName, artifact.File)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error CreateFormFile: ", err.Error())
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(artifact.File)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error os.Open(artifact.File): ", err.Error())
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(fileWriter, file)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error io.Copy(fileWriter, file): ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error writer.Close(): ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
url = fmt.Sprintf("%s/service/rest/v1/components?repository=%s", n.ServerUrl, n.Repository)
|
||||
|
||||
req, err := http.NewRequest("POST", url, body)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error http.NewRequest: ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(n.UserName, n.Password)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
resp, err := n.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error n.HttpClient.Do(req): ", err.Error())
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
LogPrintln(n, "Error upload failed with status: ", resp.StatusCode)
|
||||
return fmt.Errorf("Upload failed with status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) addFailedArtifact(artifact Artifact, errMsg string) {
|
||||
n.Failed = append(n.Failed, FailedArtifact{
|
||||
File: artifact.File,
|
||||
ArtifactId: artifact.ArtifactId,
|
||||
Err: errMsg,
|
||||
})
|
||||
}
|
||||
@@ -5,7 +5,16 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Plugin interface {
|
||||
@@ -103,3 +112,434 @@ func Exec(ctx context.Context, args Args) (Plugin, error) {
|
||||
|
||||
return plugin, nil
|
||||
}
|
||||
|
||||
type HttpClient interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
type NexusPlugin struct {
|
||||
InputArgs *Args
|
||||
IsMultiFileUpload bool
|
||||
PluginProcessingInfo
|
||||
NexusPluginResponse
|
||||
HttpClient HttpClient
|
||||
}
|
||||
|
||||
type PluginProcessingInfo struct {
|
||||
UserName string
|
||||
Password string
|
||||
ServerUrl string
|
||||
Version string
|
||||
Format string
|
||||
Repository string
|
||||
GroupId string
|
||||
Artifacts []Artifact
|
||||
}
|
||||
|
||||
type NexusPluginResponse struct {
|
||||
Failed []FailedArtifact `json:"failed"`
|
||||
}
|
||||
|
||||
type FailedArtifact struct {
|
||||
File string `json:"file"`
|
||||
ArtifactId string `json:"artifactId"`
|
||||
Err string `json:"err"`
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) Run() error {
|
||||
LogPrintln(n, "Starting Nexus Plugin Run")
|
||||
|
||||
if n.HttpClient == nil {
|
||||
n.HttpClient = &http.Client{}
|
||||
}
|
||||
|
||||
for _, artifact := range n.Artifacts {
|
||||
filePath := artifact.File
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("could not open file: %v", err))
|
||||
continue
|
||||
}
|
||||
|
||||
if n.Version == "nexus2" {
|
||||
artifactURL := n.prepareNexus2ArtifactURL(artifact)
|
||||
if err := n.uploadFileNexus2(artifactURL, file, filePath); err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("upload failed: %v", err))
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
} else if n.Version == "nexus3" {
|
||||
if err := n.uploadFileNexus3(artifact, filePath); err != nil {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("upload failed: %v", err))
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error closing file: ", err.Error())
|
||||
}
|
||||
|
||||
fmt.Println("Successfully uploaded artifact:", filePath)
|
||||
}
|
||||
|
||||
if len(n.Failed) > 0 {
|
||||
return GetNewError("NexusPlugin Error in Run: some artifacts failed to upload")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) WriteOutputVariables() error {
|
||||
|
||||
type EnvKvPair struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
var kvPairs []EnvKvPair
|
||||
|
||||
if len(n.Failed) == 0 {
|
||||
LogPrintln(n, "All artifacts uploaded successfully")
|
||||
kvPairs = append(kvPairs, EnvKvPair{Key: "UPLOAD_STATUS", Value: "Success"})
|
||||
} else {
|
||||
kvPairs = append(kvPairs, EnvKvPair{Key: "UPLOAD_STATUS", Value: n.Failed})
|
||||
}
|
||||
|
||||
var retErr error = nil
|
||||
|
||||
for _, kvPair := range kvPairs {
|
||||
err := WriteEnvVariableAsString(kvPair.Key, kvPair.Value)
|
||||
if err != nil {
|
||||
retErr = err
|
||||
}
|
||||
}
|
||||
|
||||
return retErr
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) Init(args *Args) error {
|
||||
n.InputArgs = args
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) SetBuildRoot(buildRootPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DeInit() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) ValidateAndProcessArgs(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin BuildAndValidateArgs")
|
||||
|
||||
err := n.DetermineIsMultiFileUpload(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if n.IsMultiFileUpload {
|
||||
err = n.IsMultiFileUploadArgsOk(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err = n.IsSingleFileUploadArgsOk(args)
|
||||
if err != nil {
|
||||
LogPrintln(n, "NexusPlugin Error in ValidateAndProcessArgs: "+err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DetermineIsMultiFileUpload(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin DetermineIsMultiFileUpload")
|
||||
|
||||
switch {
|
||||
case args.Attributes != "" && args.Artifact == "":
|
||||
n.IsMultiFileUpload = false
|
||||
case args.Artifact != "" && args.Attributes == "":
|
||||
n.IsMultiFileUpload = true
|
||||
case args.Attributes == "" && args.Artifact == "":
|
||||
return GetNewError("Error in DetermineCompatibilityMode: both 'Attributes' and 'Artifact' cannot be empty")
|
||||
default:
|
||||
return GetNewError("Error in DetermineCompatibilityMode: both 'Attributes' and 'Artifact' provided, which is ambiguous")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsMultiFileUploadArgsOk(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin IsMultiFileUploadArgsOk")
|
||||
|
||||
requiredArgs := map[string]string{
|
||||
"username": args.Username,
|
||||
"password": args.Password,
|
||||
"protocol": args.Protocol,
|
||||
"nexusUrl": args.ServerUrl,
|
||||
"nexusVersion": args.NexusVersion,
|
||||
"repository": args.Repository,
|
||||
"groupId": args.GroupId,
|
||||
"format": args.Format,
|
||||
}
|
||||
|
||||
for field, value := range requiredArgs {
|
||||
if value == "" {
|
||||
return GetNewError("Error in IsMultiFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
|
||||
n.UserName = args.Username
|
||||
n.Password = args.Password
|
||||
n.Repository = args.Repository
|
||||
n.ServerUrl = args.Protocol + "://" + args.ServerUrl
|
||||
n.GroupId = args.GroupId
|
||||
n.Version = args.NexusVersion
|
||||
n.Format = args.Format
|
||||
|
||||
// Unmarshalling YAML artifact data
|
||||
var artifacts []Artifact
|
||||
if err := yaml.Unmarshal([]byte(args.Artifact), &artifacts); err != nil {
|
||||
return GetNewError("Error in IsMultiFileUploadArgsOk: Error decoding YAML: " + err.Error())
|
||||
}
|
||||
|
||||
var filteredArtifacts []Artifact
|
||||
for _, artifact := range artifacts {
|
||||
missingFields := []string{}
|
||||
if artifact.ArtifactId == "" {
|
||||
missingFields = append(missingFields, "ArtifactId")
|
||||
}
|
||||
if artifact.File == "" {
|
||||
missingFields = append(missingFields, "File")
|
||||
}
|
||||
if artifact.Type == "" {
|
||||
missingFields = append(missingFields, "Type")
|
||||
}
|
||||
if artifact.Version == "" {
|
||||
missingFields = append(missingFields, "Version")
|
||||
}
|
||||
if artifact.GroupId == "" {
|
||||
artifact.GroupId = args.GroupId
|
||||
}
|
||||
if len(missingFields) > 0 {
|
||||
n.addFailedArtifact(artifact, fmt.Sprintf("Missing fields: %s", strings.Join(missingFields, ", ")))
|
||||
} else {
|
||||
// Add to filtered list if all fields are valid
|
||||
filteredArtifacts = append(filteredArtifacts, artifact)
|
||||
}
|
||||
}
|
||||
|
||||
n.Artifacts = filteredArtifacts
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsSingleFileUploadArgsOk(args Args) error {
|
||||
LogPrintln(n, "NexusPlugin IsSingleFileUploadArgsOk")
|
||||
|
||||
requiredArgs := map[string]string{
|
||||
"Username": args.Username,
|
||||
"Password": args.Password,
|
||||
"ServerUrl": args.ServerUrl,
|
||||
"Filename": args.Filename,
|
||||
"Format": args.Format,
|
||||
"Repository": args.Repository,
|
||||
}
|
||||
|
||||
for field, value := range requiredArgs {
|
||||
if value == "" {
|
||||
return GetNewError("Error in IsSingleFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
|
||||
requiredFields := []string{"CgroupId", "Cversion", "Aextension", "Aclassifier"}
|
||||
values := make(map[string]string)
|
||||
|
||||
pattern := regexp.MustCompile(`-(CgroupId|CartifactId|Cversion|Aextension|Aclassifier)=(\S+)`)
|
||||
matches := pattern.FindAllStringSubmatch(args.Attributes, -1)
|
||||
|
||||
for _, match := range matches {
|
||||
if len(match) == 3 {
|
||||
values[match[1]] = match[2]
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all required fields are present
|
||||
for _, field := range requiredFields {
|
||||
if values[field] == "" {
|
||||
return GetNewError("Error in IsSingleFileUploadArgsOk: " + field + " cannot be empty")
|
||||
}
|
||||
}
|
||||
n.UserName = args.Username
|
||||
n.Password = args.Password
|
||||
n.Repository = args.Repository
|
||||
n.ServerUrl = args.ServerUrl
|
||||
n.Format = args.Format
|
||||
n.GroupId = values["CgroupId"]
|
||||
n.Version = "nexus3"
|
||||
n.Artifacts = []Artifact{
|
||||
{
|
||||
File: args.Filename,
|
||||
Classifier: values["Aclassifier"],
|
||||
ArtifactId: values["CartifactId"],
|
||||
Type: values["Aextension"],
|
||||
Version: values["Cversion"],
|
||||
GroupId: values["CgroupId"],
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) DoPostArgsValidationSetup(args Args) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) PersistResults() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) IsQuiet() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) InspectProcessArgs(argNamesList []string) (map[string]interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func GetNewNexusPlugin() NexusPlugin {
|
||||
return NexusPlugin{}
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) prepareNexus2ArtifactURL(artifact Artifact) string {
|
||||
switch n.Format {
|
||||
case "maven2":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s/%s/%s-%s.%s",
|
||||
n.ServerUrl, n.Repository, artifact.GroupId, artifact.ArtifactId, artifact.Version,
|
||||
artifact.ArtifactId, artifact.Version, artifact.Type)
|
||||
|
||||
case "yum":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s",
|
||||
n.ServerUrl, n.Repository, artifact.ArtifactId, artifact.Version)
|
||||
|
||||
case "raw":
|
||||
return fmt.Sprintf("%s/repository/%s/%s/%s.%s",
|
||||
n.ServerUrl, n.Repository, artifact.GroupId, artifact.ArtifactId, artifact.Type)
|
||||
|
||||
default:
|
||||
LogPrintln(n, "Unsupported format for direct upload:", n.Format)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) uploadFileNexus2(url string, content io.Reader, filePath string) error {
|
||||
req, err := http.NewRequest("PUT", url, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(n.UserName, n.Password)
|
||||
req.Header.Set("Content-Type", "application/octet-stream")
|
||||
|
||||
resp, err := n.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
fmt.Println("File upload failed status ", resp.StatusCode)
|
||||
return fmt.Errorf("Upload failed with status %d", resp.StatusCode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) uploadFileNexus3(artifact Artifact, filePath string) error {
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
var url string
|
||||
var assetFieldName string
|
||||
|
||||
switch n.Format {
|
||||
case "maven2":
|
||||
_ = writer.WriteField("maven2.groupId", artifact.GroupId)
|
||||
_ = writer.WriteField("maven2.artifactId", artifact.ArtifactId)
|
||||
_ = writer.WriteField("maven2.version", artifact.Version)
|
||||
assetFieldName = "maven2.asset1"
|
||||
_ = writer.WriteField("maven2.asset1.extension", artifact.Type)
|
||||
|
||||
case "raw":
|
||||
_ = writer.WriteField("raw.directory", artifact.GroupId)
|
||||
assetFieldName = "raw.asset1"
|
||||
_ = writer.WriteField("raw.asset1.filename", fmt.Sprintf("%s.%s", artifact.ArtifactId, artifact.Type))
|
||||
|
||||
default:
|
||||
assetFieldName = fmt.Sprintf("%s.asset", n.Format)
|
||||
}
|
||||
|
||||
fileWriter, err := writer.CreateFormFile(assetFieldName, artifact.File)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error CreateFormFile: ", err.Error())
|
||||
return err
|
||||
}
|
||||
file, err := os.Open(artifact.File)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error os.Open(artifact.File): ", err.Error())
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = io.Copy(fileWriter, file)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error io.Copy(fileWriter, file): ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error writer.Close(): ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
url = fmt.Sprintf("%s/service/rest/v1/components?repository=%s", n.ServerUrl, n.Repository)
|
||||
|
||||
req, err := http.NewRequest("POST", url, body)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error http.NewRequest: ", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
req.SetBasicAuth(n.UserName, n.Password)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
resp, err := n.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
LogPrintln(n, "Error n.HttpClient.Do(req): ", err.Error())
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 400 {
|
||||
LogPrintln(n, "Error upload failed with status: ", resp.StatusCode)
|
||||
return fmt.Errorf("Upload failed with status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NexusPlugin) addFailedArtifact(artifact Artifact, errMsg string) {
|
||||
n.Failed = append(n.Failed, FailedArtifact{
|
||||
File: artifact.File,
|
||||
ArtifactId: artifact.ArtifactId,
|
||||
Err: errMsg,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user