Compare commits

..

No commits in common. "main" and "v3.0.1" have entirely different histories.
main ... v3.0.1

15 changed files with 417 additions and 284 deletions

297
.drone.yml Normal file
View File

@ -0,0 +1,297 @@
---
kind: pipeline
name: test
platform:
os: linux
arch: amd64
steps:
- name: deps
image: golang:1.19
commands:
- make deps
volumes:
- name: godeps
path: /go
- name: lint
image: golang:1.19
commands:
- make lint
volumes:
- name: godeps
path: /go
- name: test
image: golang:1.19
commands:
- make test
volumes:
- name: godeps
path: /go
volumes:
- name: godeps
temp: {}
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
---
kind: pipeline
name: build-binaries
platform:
os: linux
arch: amd64
steps:
- name: build
image: techknowlogick/xgo:go-1.19.x
commands:
- ln -s /drone/src /source
- make release
- name: executable
image: alpine
commands:
- $(find dist/ -executable -type f -iname ${DRONE_REPO_NAME}-linux-amd64) --help
- name: changelog-generate
image: thegeeklab/git-chglog
commands:
- git fetch -tq
- git-chglog --no-color --no-emoji -o CHANGELOG.md ${DRONE_TAG:---next-tag unreleased unreleased}
- name: changelog-format
image: thegeeklab/alpine-tools
commands:
- prettier CHANGELOG.md
- prettier -w CHANGELOG.md
- name: publish
image: plugins/github-release
settings:
api_key:
from_secret: github_token
files:
- dist/*
note: CHANGELOG.md
overwrite: true
title: ${DRONE_TAG}
when:
ref:
- refs/tags/**
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
depends_on:
- test
---
kind: pipeline
name: build-container
platform:
os: linux
arch: amd64
steps:
- name: dryrun
image: thegeeklab/drone-docker-buildx:20
settings:
dockerfile: Dockerfile.multiarch
dry_run: true
platforms:
- linux/amd64
- linux/arm64
- linux/arm/v7
- linux/arm/v6
provenance: false
repo: thegeeklab/${DRONE_REPO_NAME}
when:
ref:
- refs/pull/**
- name: publish-dockerhub
image: thegeeklab/drone-docker-buildx:20
settings:
auto_tag: true
dockerfile: Dockerfile.multiarch
password:
from_secret: docker_password
platforms:
- linux/amd64
- linux/arm64
- linux/arm/v7
- linux/arm/v6
provenance: false
repo: thegeeklab/${DRONE_REPO_NAME}
username:
from_secret: docker_username
when:
ref:
- refs/heads/main
- refs/tags/**
depends_on:
- dryrun
- name: publish-quay
image: thegeeklab/drone-docker-buildx:20
settings:
auto_tag: true
dockerfile: Dockerfile.multiarch
password:
from_secret: quay_password
platforms:
- linux/amd64
- linux/arm64
- linux/arm/v7
- linux/arm/v6
provenance: false
registry: quay.io
repo: quay.io/thegeeklab/${DRONE_REPO_NAME}
username:
from_secret: quay_username
when:
ref:
- refs/heads/main
- refs/tags/**
depends_on:
- dryrun
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
depends_on:
- test
---
kind: pipeline
name: docs
platform:
os: linux
arch: amd64
concurrency:
limit: 1
steps:
- name: markdownlint
image: thegeeklab/markdownlint-cli
commands:
- markdownlint 'docs/content/**/*.md' 'README.md' 'CONTRIBUTING.md'
- name: spellcheck
image: thegeeklab/alpine-tools
commands:
- spellchecker --files '_docs/**/*.md' 'README.md' 'CONTRIBUTING.md' -d .dictionary -p spell indefinite-article syntax-urls --no-suggestions
environment:
FORCE_COLOR: true
NPM_CONFIG_LOGLEVEL: error
- name: publish
image: thegeeklab/drone-git-action
settings:
action:
- pages
author_email: bot@thegeeklab.de
author_name: thegeeklab-bot
branch: docs
message: auto-update documentation
netrc_password:
from_secret: github_token
pages_directory: _docs/
when:
ref:
- refs/heads/main
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
depends_on:
- build-binaries
- build-container
---
kind: pipeline
name: notifications
platform:
os: linux
arch: amd64
steps:
- name: pushrm-dockerhub
image: chko/docker-pushrm:1
environment:
DOCKER_PASS:
from_secret: docker_password
DOCKER_USER:
from_secret: docker_username
PUSHRM_FILE: README.md
PUSHRM_SHORT: Drone plugin to synchronize a directory with an S3 bucket
PUSHRM_TARGET: thegeeklab/${DRONE_REPO_NAME}
when:
status:
- success
- name: pushrm-quay
image: chko/docker-pushrm:1
environment:
APIKEY__QUAY_IO:
from_secret: quay_token
PUSHRM_FILE: README.md
PUSHRM_TARGET: quay.io/thegeeklab/${DRONE_REPO_NAME}
when:
status:
- success
- name: matrix
image: thegeeklab/drone-matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
template: "Status: **{{ build.Status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.Link }}){{#if build.Branch}} ({{ build.Branch }}){{/if}} by {{ commit.Author }}<br/> Message: {{ commit.Message.Title }}"
username:
from_secret: matrix_username
when:
status:
- success
- failure
trigger:
ref:
- refs/heads/main
- refs/tags/**
status:
- success
- failure
depends_on:
- docs
---
kind: signature
hmac: 944cf1fa4e35a0f1a4634335ec63ed97dd0f9059d05311fd2211595a7f7626b7
...

View File

@ -1,91 +1,25 @@
linters:
enable:
- gosimple
- deadcode
- typecheck
- govet
- errcheck
- staticcheck
- unused
- structcheck
- varcheck
- dupl
- gofmt
- misspell
- gocritic
- bidichk
- ineffassign
- revive
- gofumpt
- depguard
enable-all: false
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- decorder
- dogsled
- dupl
- dupword
- durationcheck
- errchkjson
- errname
- errorlint
- execinquery
- exhaustive
- exportloopref
- forcetypeassert
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofmt
- gofumpt
- goheader
- goimports
- gomnd
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- grouper
- importas
- interfacebloat
- ireturn
- lll
- loggercheck
- maintidx
- makezero
- misspell
- musttag
- nakedret
- nestif
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- nonamedreturns
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
# - rowserrcheck
# - sqlclosecheck
# - structcheck
- stylecheck
- tagliatelle
- tenv
- testableexamples
- thelper
- tparallel
- unconvert
- unparam
- usestdlibvars
# - wastedassign
- whitespace
- wsl
fast: false
run:
@ -94,4 +28,4 @@ run:
linters-settings:
gofumpt:
extra-rules: true
lang-version: "1.20"
lang-version: "1.18"

View File

@ -3,7 +3,7 @@
## Security
If you think you have found a **security issue**, please do not mention it in this repository.
Instead, send an email to `security@thegeeklab.de` with as many details as possible so it can be handled confidential.
Instead, send an email to security@thegeeklab.de with as many details as possible so it can be handled confidential.
## Bug Reports and Feature Requests

View File

@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.20@sha256:839ba88412b5d3e12d66ed4774a85fc6e6c644dce8074ab82c798e5db27d4a09 as build
FROM --platform=$BUILDPLATFORM golang:1.19@sha256:bb9811fad43a7d6fd2173248d8331b2dcf5ac9af20976b1937ecd214c5b8c383 as build
ARG TARGETOS
ARG TARGETARCH
@ -8,7 +8,7 @@ WORKDIR /src
RUN make build
FROM alpine:3.18@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
FROM alpine:3.17@sha256:f271e74b17ced29b915d351685fd4644785c6d1559dd1f2d4189a5e851ef753a
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.5.0
GOFUMPT_PACKAGE_VERSION := v0.4.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.54.1
GOLANGCI_LINT_PACKAGE_VERSION := v1.50.1
EXECUTABLE := drone-s3-sync
@ -19,7 +19,7 @@ GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(G
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GENERATE ?=
XGO_VERSION := go-1.20.x
XGO_VERSION := go-1.19.x
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
TARGETOS ?= linux

View File

@ -1,6 +1,6 @@
# drone-s3-sync
DISCONTINUED: Drone plugin to synchronize a directory with an S3 bucket
Drone plugin to synchronize a directory with an S3 bucket
[![Build Status](https://img.shields.io/drone/build/thegeeklab/drone-s3-sync?logo=drone&server=https%3A%2F%2Fdrone.thegeeklab.de)](https://drone.thegeeklab.de/thegeeklab/drone-s3-sync)
[![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/drone-s3-sync)
@ -10,8 +10,6 @@ DISCONTINUED: Drone plugin to synchronize a directory with an S3 bucket
[![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/drone-s3-sync)
[![License: MIT](https://img.shields.io/github/license/thegeeklab/drone-s3-sync)](https://github.com/thegeeklab/drone-s3-sync/blob/main/LICENSE)
> **DISCONTINUED:** As I don't use Drone CI anymore, this project is unmaintained. If you are interested in a free and open source CI system check out [Woodpecker CI](https://woodpecker-ci.org/).
Drone plugin to synchronize a directory with an S3 bucket. You can find the full documentation at [https://drone-plugin-index.geekdocs.de](https://drone-plugin-index.geekdocs.de/plugins/drone-s3-sync).
## Contributors

View File

@ -134,9 +134,8 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag {
Category: category,
},
&cli.IntFlag{
Name: "max-concurrency",
Usage: "customize number concurrent files to process",
//nolint:gomnd
Name: "max-concurrency",
Usage: "customize number concurrent files to process",
Value: 100,
EnvVars: []string{"PLUGIN_MAX_CONCURRENCY"},
Destination: &settings.MaxConcurrency,

View File

@ -1,7 +1,6 @@
package main
import (
"errors"
"fmt"
"os"
@ -12,14 +11,11 @@ import (
"github.com/urfave/cli/v2"
)
//nolint:gochecknoglobals
var (
BuildVersion = "devel"
BuildDate = "00000000"
)
var ErrTypeAssertionFailed = errors.New("type assertion failed")
func main() {
settings := &plugin.Settings{}
@ -48,42 +44,12 @@ func run(settings *plugin.Settings) cli.ActionFunc {
return func(ctx *cli.Context) error {
urfave.LoggingFromContext(ctx)
acl, ok := ctx.Generic("acl").(*StringMapFlag)
if !ok {
return fmt.Errorf("%w: failed to read acl input", ErrTypeAssertionFailed)
}
cacheControl, ok := ctx.Generic("cache-control").(*StringMapFlag)
if !ok {
return fmt.Errorf("%w: failed to read cache-control input", ErrTypeAssertionFailed)
}
contentType, ok := ctx.Generic("content-type").(*StringMapFlag)
if !ok {
return fmt.Errorf("%w: failed to read content-type input", ErrTypeAssertionFailed)
}
contentEncoding, ok := ctx.Generic("content-encoding").(*StringMapFlag)
if !ok {
return fmt.Errorf("%w: failed to read content-encoding input", ErrTypeAssertionFailed)
}
metadata, ok := ctx.Generic("metadata").(*DeepStringMapFlag)
if !ok {
return fmt.Errorf("%w: failed to read metadata input", ErrTypeAssertionFailed)
}
redirects, ok := ctx.Generic("redirects").(*MapFlag)
if !ok {
return fmt.Errorf("%w: failed to read redirects input", ErrTypeAssertionFailed)
}
settings.ACL = acl.Get()
settings.CacheControl = cacheControl.Get()
settings.ContentType = contentType.Get()
settings.ContentEncoding = contentEncoding.Get()
settings.Metadata = metadata.Get()
settings.Redirects = redirects.Get()
settings.ACL = ctx.Generic("acl").(*StringMapFlag).Get()
settings.CacheControl = ctx.Generic("cache-control").(*StringMapFlag).Get()
settings.ContentType = ctx.Generic("content-type").(*StringMapFlag).Get()
settings.ContentEncoding = ctx.Generic("content-encoding").(*StringMapFlag).Get()
settings.Metadata = ctx.Generic("metadata").(*DeepStringMapFlag).Get()
settings.Redirects = ctx.Generic("redirects").(*MapFlag).Get()
plugin := plugin.New(
*settings,

View File

@ -18,11 +18,9 @@ func (d *DeepStringMapFlag) Get() map[string]map[string]string {
func (d *DeepStringMapFlag) Set(value string) error {
d.parts = map[string]map[string]string{}
err := json.Unmarshal([]byte(value), &d.parts)
if err != nil {
single := map[string]string{}
err := json.Unmarshal([]byte(value), &single)
if err != nil {
return err
@ -48,12 +46,10 @@ func (s *StringMapFlag) Get() map[string]string {
func (s *StringMapFlag) Set(value string) error {
s.parts = map[string]string{}
err := json.Unmarshal([]byte(value), &s.parts)
if err != nil {
s.parts["*"] = value
}
return nil
}
@ -71,6 +67,5 @@ func (m *MapFlag) Get() map[string]string {
func (m *MapFlag) Set(value string) error {
m.parts = map[string]string{}
return json.Unmarshal([]byte(value), &m.parts)
}

14
go.mod
View File

@ -1,14 +1,14 @@
module github.com/thegeeklab/drone-s3-sync
go 1.20
go 1.19
require (
github.com/aws/aws-sdk-go v1.44.302
github.com/joho/godotenv v1.5.1
github.com/aws/aws-sdk-go v1.44.180
github.com/joho/godotenv v1.4.0
github.com/ryanuber/go-glob v1.0.0
github.com/sirupsen/logrus v1.9.3
github.com/thegeeklab/drone-plugin-lib/v2 v2.3.4
github.com/urfave/cli/v2 v2.25.7
github.com/sirupsen/logrus v1.9.0
github.com/thegeeklab/drone-plugin-lib/v2 v2.2.1
github.com/urfave/cli/v2 v2.23.7
)
require (
@ -16,5 +16,5 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/sys v0.1.0 // indirect
)

23
go.sum
View File

@ -1,5 +1,5 @@
github.com/aws/aws-sdk-go v1.44.302 h1:ST3ko6GrJKn3Xi+nAvxjG3uk/V1pW8KC52WLeIxqqNk=
github.com/aws/aws-sdk-go v1.44.302/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.180 h1:VLZuAHI9fa/3WME5JjpVjcPCNfpGHVMiHx8sLHWhMgI=
github.com/aws/aws-sdk-go v1.44.180/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -9,8 +9,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -18,15 +18,15 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/thegeeklab/drone-plugin-lib/v2 v2.3.4 h1:Quzrike/xRAR0izxQ0d+ocJyIUm4h1497Oyo9grcRzg=
github.com/thegeeklab/drone-plugin-lib/v2 v2.3.4/go.mod h1:qWVUZCmwL0Ntwa/hvyqM03EeIr1ReBR2XJsmIc7MGus=
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/thegeeklab/drone-plugin-lib/v2 v2.2.1 h1:fta32M+y6aHG/BX+Kwxo9DQAcYpTyCBHn7sAm2qjfL0=
github.com/thegeeklab/drone-plugin-lib/v2 v2.2.1/go.mod h1:Bu++VS6GXEWCHQdzR65dPsGtBGOMuqAQPiRVBaa+HrY=
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@ -46,9 +46,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -1,9 +1,7 @@
package plugin
import (
//nolint:gosec
"crypto/md5"
"errors"
"fmt"
"io"
"mime"
@ -30,20 +28,20 @@ type AWS struct {
plugin *Plugin
}
func NewAWS(plugin *Plugin) AWS {
func NewAWS(p *Plugin) AWS {
sessCfg := &aws.Config{
S3ForcePathStyle: aws.Bool(plugin.settings.PathStyle),
Region: aws.String(plugin.settings.Region),
S3ForcePathStyle: aws.Bool(p.settings.PathStyle),
Region: aws.String(p.settings.Region),
}
if plugin.settings.Endpoint != "" {
sessCfg.Endpoint = &plugin.settings.Endpoint
sessCfg.DisableSSL = aws.Bool(strings.HasPrefix(plugin.settings.Endpoint, "http://"))
if p.settings.Endpoint != "" {
sessCfg.Endpoint = &p.settings.Endpoint
sessCfg.DisableSSL = aws.Bool(strings.HasPrefix(p.settings.Endpoint, "http://"))
}
// allowing to use the instance role or provide a key and secret
if plugin.settings.AccessKey != "" && plugin.settings.SecretKey != "" {
sessCfg.Credentials = credentials.NewStaticCredentials(plugin.settings.AccessKey, plugin.settings.SecretKey, "")
if p.settings.AccessKey != "" && p.settings.SecretKey != "" {
sessCfg.Credentials = credentials.NewStaticCredentials(p.settings.AccessKey, p.settings.SecretKey, "")
}
sess, _ := session.NewSession(sessCfg)
@ -53,13 +51,11 @@ func NewAWS(plugin *Plugin) AWS {
r := make([]string, 1)
l := make([]string, 1)
return AWS{c, cf, r, l, plugin}
return AWS{c, cf, r, l, p}
}
//nolint:gocognit,gocyclo,maintidx
func (a *AWS) Upload(local, remote string) error {
plugin := a.plugin
p := a.plugin
if local == "" {
return nil
}
@ -72,11 +68,9 @@ func (a *AWS) Upload(local, remote string) error {
defer file.Close()
var acl string
for pattern := range plugin.settings.ACL {
for pattern := range p.settings.ACL {
if match := glob.Glob(pattern, local); match {
acl = plugin.settings.ACL[pattern]
acl = p.settings.ACL[pattern]
break
}
}
@ -88,11 +82,9 @@ func (a *AWS) Upload(local, remote string) error {
fileExt := filepath.Ext(local)
var contentType string
for patternExt := range plugin.settings.ContentType {
for patternExt := range p.settings.ContentType {
if patternExt == fileExt {
contentType = plugin.settings.ContentType[patternExt]
contentType = p.settings.ContentType[patternExt]
break
}
}
@ -102,58 +94,43 @@ func (a *AWS) Upload(local, remote string) error {
}
var contentEncoding string
for patternExt := range plugin.settings.ContentEncoding {
for patternExt := range p.settings.ContentEncoding {
if patternExt == fileExt {
contentEncoding = plugin.settings.ContentEncoding[patternExt]
contentEncoding = p.settings.ContentEncoding[patternExt]
break
}
}
var cacheControl string
for pattern := range plugin.settings.CacheControl {
for pattern := range p.settings.CacheControl {
if match := glob.Glob(pattern, local); match {
cacheControl = plugin.settings.CacheControl[pattern]
cacheControl = p.settings.CacheControl[pattern]
break
}
}
metadata := map[string]*string{}
for pattern := range plugin.settings.Metadata {
for pattern := range p.settings.Metadata {
if match := glob.Glob(pattern, local); match {
for k, v := range plugin.settings.Metadata[pattern] {
for k, v := range p.settings.Metadata[pattern] {
metadata[k] = aws.String(v)
}
break
}
}
var AWSErr awserr.Error
head, err := a.client.HeadObject(&s3.HeadObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
})
if err != nil && errors.As(err, &AWSErr) {
//nolint:errorlint,forcetypeassert
if err != nil && err.(awserr.Error).Code() != "404" {
if err.(awserr.Error).Code() == "404" {
return err
}
logrus.Debugf(
"'%s' not found in bucket, uploading with content-type '%s' and permissions '%s'",
local,
contentType,
acl,
)
logrus.Debugf("'%s' not found in bucket, uploading with content-type '%s' and permissions '%s'", local, contentType, acl)
putObject := &s3.PutObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
Body: file,
ContentType: aws.String(contentType),
@ -175,58 +152,48 @@ func (a *AWS) Upload(local, remote string) error {
}
_, err = a.client.PutObject(putObject)
return err
}
//nolint:gosec
hash := md5.New()
_, _ = io.Copy(hash, file)
sum := fmt.Sprintf("'%x'", hash.Sum(nil))
//nolint:nestif
if sum == *head.ETag {
shouldCopy := false
if head.ContentType == nil && contentType != "" {
logrus.Debugf("content-type has changed from unset to %s", contentType)
shouldCopy = true
}
if !shouldCopy && head.ContentType != nil && contentType != *head.ContentType {
logrus.Debugf("content-type has changed from %s to %s", *head.ContentType, contentType)
shouldCopy = true
}
if !shouldCopy && head.ContentEncoding == nil && contentEncoding != "" {
logrus.Debugf("Content-Encoding has changed from unset to %s", contentEncoding)
shouldCopy = true
}
if !shouldCopy && head.ContentEncoding != nil && contentEncoding != *head.ContentEncoding {
logrus.Debugf("Content-Encoding has changed from %s to %s", *head.ContentEncoding, contentEncoding)
shouldCopy = true
}
if !shouldCopy && head.CacheControl == nil && cacheControl != "" {
logrus.Debugf("cache-control has changed from unset to %s", cacheControl)
shouldCopy = true
}
if !shouldCopy && head.CacheControl != nil && cacheControl != *head.CacheControl {
logrus.Debugf("cache-control has changed from %s to %s", *head.CacheControl, cacheControl)
shouldCopy = true
}
if !shouldCopy && len(head.Metadata) != len(metadata) {
logrus.Debugf("count of metadata values has changed for %s", local)
shouldCopy = true
}
@ -235,9 +202,7 @@ func (a *AWS) Upload(local, remote string) error {
if hv, ok := head.Metadata[k]; ok {
if *v != *hv {
logrus.Debugf("metadata values have changed for %s", local)
shouldCopy = true
break
}
}
@ -246,7 +211,7 @@ func (a *AWS) Upload(local, remote string) error {
if !shouldCopy {
grant, err := a.client.GetObjectAcl(&s3.GetObjectAclInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
})
if err != nil {
@ -254,20 +219,18 @@ func (a *AWS) Upload(local, remote string) error {
}
previousACL := "private"
for _, grant := range grant.Grants {
grantee := *grant.Grantee
if grantee.URI != nil {
if *grantee.URI == "http://acs.amazonaws.com/groups/global/AllUsers" {
if *grant.Permission == "READ" {
for _, g := range grant.Grants {
gt := *g.Grantee
if gt.URI != nil {
if *gt.URI == "http://acs.amazonaws.com/groups/global/AllUsers" {
if *g.Permission == "READ" {
previousACL = "public-read"
} else if *grant.Permission == "WRITE" {
} else if *g.Permission == "WRITE" {
previousACL = "public-read-write"
}
}
if *grantee.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" {
if *grant.Permission == "READ" {
if *gt.URI == "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" {
if *g.Permission == "READ" {
previousACL = "authenticated-read"
}
}
@ -276,23 +239,20 @@ func (a *AWS) Upload(local, remote string) error {
if previousACL != acl {
logrus.Debugf("permissions for '%s' have changed from '%s' to '%s'", remote, previousACL, acl)
shouldCopy = true
}
}
if !shouldCopy {
logrus.Debugf("skipping '%s' because hashes and metadata match", local)
return nil
}
logrus.Debugf("updating metadata for '%s' content-type: '%s', ACL: '%s'", local, contentType, acl)
copyObject := &s3.CopyObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
CopySource: aws.String(fmt.Sprintf("%s/%s", plugin.settings.Bucket, remote)),
CopySource: aws.String(fmt.Sprintf("%s/%s", p.settings.Bucket, remote)),
ACL: aws.String(acl),
ContentType: aws.String(contentType),
Metadata: metadata,
@ -313,7 +273,6 @@ func (a *AWS) Upload(local, remote string) error {
}
_, err = a.client.CopyObject(copyObject)
return err
}
@ -323,9 +282,8 @@ func (a *AWS) Upload(local, remote string) error {
}
logrus.Debugf("uploading '%s' with content-type '%s' and permissions '%s'", local, contentType, acl)
putObject := &s3.PutObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
Body: file,
ContentType: aws.String(contentType),
@ -347,13 +305,11 @@ func (a *AWS) Upload(local, remote string) error {
}
_, err = a.client.PutObject(putObject)
return err
}
func (a *AWS) Redirect(path, location string) error {
plugin := a.plugin
p := a.plugin
logrus.Debugf("adding redirect from '%s' to '%s'", path, location)
if a.plugin.settings.DryRun {
@ -361,18 +317,16 @@ func (a *AWS) Redirect(path, location string) error {
}
_, err := a.client.PutObject(&s3.PutObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(path),
ACL: aws.String("public-read"),
WebsiteRedirectLocation: aws.String(location),
})
return err
}
func (a *AWS) Delete(remote string) error {
plugin := a.plugin
p := a.plugin
logrus.Debugf("removing remote file '%s'", remote)
if a.plugin.settings.DryRun {
@ -380,20 +334,17 @@ func (a *AWS) Delete(remote string) error {
}
_, err := a.client.DeleteObject(&s3.DeleteObjectInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Key: aws.String(remote),
})
return err
}
func (a *AWS) List(path string) ([]string, error) {
plugin := a.plugin
remote := make([]string, 0)
p := a.plugin
remote := make([]string, 1)
resp, err := a.client.ListObjects(&s3.ListObjectsInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Prefix: aws.String(path),
})
if err != nil {
@ -406,7 +357,7 @@ func (a *AWS) List(path string) ([]string, error) {
for *resp.IsTruncated {
resp, err = a.client.ListObjects(&s3.ListObjectsInput{
Bucket: aws.String(plugin.settings.Bucket),
Bucket: aws.String(p.settings.Bucket),
Prefix: aws.String(path),
Marker: aws.String(remote[len(remote)-1]),
})
@ -425,9 +376,7 @@ func (a *AWS) List(path string) ([]string, error) {
func (a *AWS) Invalidate(invalidatePath string) error {
p := a.plugin
logrus.Debugf("invalidating '%s'", invalidatePath)
_, err := a.cfClient.CreateInvalidation(&cloudfront.CreateInvalidationInput{
DistributionId: aws.String(p.settings.CloudFrontDistribution),
InvalidationBatch: &cloudfront.InvalidationBatch{
@ -440,6 +389,5 @@ func (a *AWS) Invalidate(invalidatePath string) error {
},
},
})
return err
}

View File

@ -44,13 +44,14 @@ type Result struct {
err error
}
var MissingAwsValuesMessage = "Must set 'bucket'"
// Validate handles the settings validation of the plugin.
func (p *Plugin) Validate() error {
wd, err := os.Getwd()
if err != nil {
return fmt.Errorf("error while retrieving working directory: %w", err)
}
p.settings.Source = filepath.Join(wd, p.settings.Source)
p.settings.Target = strings.TrimPrefix(p.settings.Target, "/")
@ -87,7 +88,7 @@ func (p *Plugin) createSyncJobs() error {
return err
}
local := make([]string, 0)
local := make([]string, 1)
err = filepath.Walk(p.settings.Source, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
@ -121,16 +122,13 @@ func (p *Plugin) createSyncJobs() error {
action: "redirect",
})
}
if p.settings.Delete {
for _, remote := range remote {
for _, r := range remote {
found := false
remotePath := strings.TrimPrefix(remote, p.settings.Target+"/")
rPath := strings.TrimPrefix(r, p.settings.Target+"/")
for _, l := range local {
if l == remotePath {
if l == rPath {
found = true
break
}
}
@ -138,7 +136,7 @@ func (p *Plugin) createSyncJobs() error {
if !found {
p.settings.Jobs = append(p.settings.Jobs, Job{
local: "",
remote: remote,
remote: r,
action: "delete",
})
}
@ -152,46 +150,41 @@ func (p *Plugin) runJobs() error {
client := p.settings.Client
jobChan := make(chan struct{}, p.settings.MaxConcurrency)
results := make(chan *Result, len(p.settings.Jobs))
var invalidateJob *Job
logrus.Infof("Synchronizing with bucket '%s'", p.settings.Bucket)
for _, job := range p.settings.Jobs {
for _, j := range p.settings.Jobs {
jobChan <- struct{}{}
go func(job Job) {
go func(j Job) {
var err error
switch job.action {
switch j.action {
case "upload":
err = client.Upload(job.local, job.remote)
err = client.Upload(j.local, j.remote)
case "redirect":
err = client.Redirect(job.local, job.remote)
err = client.Redirect(j.local, j.remote)
case "delete":
err = client.Delete(job.remote)
err = client.Delete(j.remote)
case "invalidateCloudFront":
invalidateJob = &job
invalidateJob = &j
default:
err = nil
}
results <- &Result{job, err}
results <- &Result{j, err}
<-jobChan
}(job)
}(j)
}
for range p.settings.Jobs {
r := <-results
if r.err != nil {
return fmt.Errorf("failed to %s %s to %s: %w", r.j.action, r.j.local, r.j.remote, r.err)
return fmt.Errorf("failed to %s %s to %s: %+v", r.j.action, r.j.local, r.j.remote, r.err)
}
}
if invalidateJob != nil {
err := client.Invalidate(invalidateJob.remote)
if err != nil {
return fmt.Errorf("failed to %s %s to %s: %w", invalidateJob.action, invalidateJob.local, invalidateJob.remote, err)
return fmt.Errorf("failed to %s %s to %s: %+v", invalidateJob.action, invalidateJob.local, invalidateJob.remote, err)
}
}

View File

@ -12,7 +12,7 @@ type Plugin struct {
}
// New initializes a plugin from the given Settings, Pipeline, and Network.
func New(settings Settings, pipeline drone.Pipeline, network drone.Network) *Plugin {
func New(settings Settings, pipeline drone.Pipeline, network drone.Network) drone.Plugin {
return &Plugin{
settings: settings,
pipeline: pipeline,

4
renovate.json Normal file
View File

@ -0,0 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>thegeeklab/renovate-presets:golang"]
}