From 2932153f5d4279bdcbe5dc21ced807a34323eda3 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Sat, 19 Aug 2023 16:00:02 +0200 Subject: [PATCH] refactor: initial commit after rewrite to woodpecker --- .chglog/config.yml | 2 +- .dictionary | 2 +- .drone.yml | 297 ------------------ .github/settings.yml | 15 +- .gitignore | 2 +- .golangci.yml | 2 +- .prettierignore | 1 - .woodpecker/build-binary.yml | 44 +++ .woodpecker/build-container.yml | 66 ++++ .woodpecker/docs.yml | 72 +++++ .woodpecker/notify.yml | 30 ++ .woodpecker/test.yml | 22 ++ ...rfile.multiarch => Containerfile.multiarch | 14 +- Makefile | 8 +- README.md | 24 +- _docs/content/_index.md | 40 ++- cmd/drone-s3-sync/main.go | 104 ------ cmd/drone-s3-sync/types.go | 76 ----- cmd/{drone-s3-sync => wp-s3-action}/config.go | 63 ++-- cmd/wp-s3-action/main.go | 28 ++ go.mod | 16 +- go.sum | 31 +- plugin/aws.go | 100 +++--- plugin/impl.go | 99 +++--- plugin/plugin.go | 61 +++- 25 files changed, 517 insertions(+), 702 deletions(-) delete mode 100644 .drone.yml create mode 100644 .woodpecker/build-binary.yml create mode 100644 .woodpecker/build-container.yml create mode 100644 .woodpecker/docs.yml create mode 100644 .woodpecker/notify.yml create mode 100644 .woodpecker/test.yml rename Dockerfile.multiarch => Containerfile.multiarch (59%) delete mode 100644 cmd/drone-s3-sync/main.go delete mode 100644 cmd/drone-s3-sync/types.go rename cmd/{drone-s3-sync => wp-s3-action}/config.go (72%) create mode 100644 cmd/wp-s3-action/main.go diff --git a/.chglog/config.yml b/.chglog/config.yml index 6ada8f4..eeee8bc 100755 --- a/.chglog/config.yml +++ b/.chglog/config.yml @@ -2,7 +2,7 @@ style: github template: CHANGELOG.tpl.md info: title: CHANGELOG - repository_url: https://github.com/thegeeklab/drone-s3-sync + repository_url: https://github.com/thegeeklab/wp-s3-action options: commit_groups: title_maps: diff --git a/.dictionary b/.dictionary index 6ff5613..7757186 100644 --- a/.dictionary +++ b/.dictionary @@ -2,7 +2,7 @@ api github url gh -drone-s3-sync +wp-s3-action (s|S)3 cloudfront Minio diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index ebec798..0000000 --- a/.drone.yml +++ /dev/null @@ -1,297 +0,0 @@ ---- -kind: pipeline -name: test - -platform: - os: linux - arch: amd64 - -steps: - - name: deps - image: golang:1.20 - commands: - - make deps - volumes: - - name: godeps - path: /go - - - name: lint - image: golang:1.20 - commands: - - make lint - volumes: - - name: godeps - path: /go - - - name: test - image: golang:1.20 - 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.20.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:23 - 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:23 - 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:23 - 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 }}**
Build: [{{ .Repo.Owner }}/{{ .Repo.Name }}]({{ .Build.Link }}){{ if .Build.Branch }} ({{ .Build.Branch }}){{ end }} by {{ .Commit.Author }}
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: dfc2eb36a2e743dc5a698a1721eac2e1e2f2702e3c53dde73e44a297c0e40744 - -... diff --git a/.github/settings.yml b/.github/settings.yml index 84f3ca4..57bace7 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -1,8 +1,8 @@ repository: - name: drone-s3-sync - description: Drone plugin to synchronize a directory with an S3 bucket - homepage: https://drone-plugin-index.geekdocs.de/plugins/drone-s3-sync - topics: drone, drone-plugin + name: wp-s3-action + description: Woodpecker CI plugin to perform S3 actions + homepage: https://wp-plugin-index.geekdocs.de/plugins/wp-s3-action + topics: woodpecker-ci, woodpecker, woodpecker-plugin private: false has_issues: true @@ -51,8 +51,11 @@ branches: required_status_checks: strict: false contexts: - - continuous-integration/drone/pr - enforce_admins: true + - ci/woodpecker/pr/test + - ci/woodpecker/pr/build-binary + - ci/woodpecker/pr/build-container + - ci/woodpecker/pr/docs + enforce_admins: false required_linear_history: true restrictions: null - name: docs diff --git a/.gitignore b/.gitignore index 1a815fe..5a8b4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /dist/ /release/ -/drone-s3-sync* +/wp-s3-action* coverage.out CHANGELOG.md diff --git a/.golangci.yml b/.golangci.yml index 342bde5..7e7ed7d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -94,4 +94,4 @@ run: linters-settings: gofumpt: extra-rules: true - lang-version: "1.20" + lang-version: "1.21" diff --git a/.prettierignore b/.prettierignore index 23a4f05..135c35d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,2 @@ -.drone.yml *.tpl.md LICENSE diff --git a/.woodpecker/build-binary.yml b/.woodpecker/build-binary.yml new file mode 100644 index 0000000..8c5bbd3 --- /dev/null +++ b/.woodpecker/build-binary.yml @@ -0,0 +1,44 @@ +--- +when: + - event: [pull_request, tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +steps: + build: + image: docker.io/techknowlogick/xgo:go-1.21.x + commands: + - ln -s $(pwd) /source + - make release + + executable: + image: docker.io/library/alpine + commands: + - $(find dist/ -executable -type f -iname ${CI_REPO_NAME}-linux-amd64) --help + + changelog-generate: + image: quay.io/thegeeklab/git-chglog + commands: + - git fetch -tq + - git-chglog --no-color --no-emoji -o CHANGELOG.md ${CI_COMMIT_TAG:---next-tag unreleased unreleased} + + changelog-format: + image: quay.io/thegeeklab/alpine-tools + commands: + - prettier CHANGELOG.md + - prettier -w CHANGELOG.md + + publish-github: + image: docker.io/plugins/github-release + settings: + api_key: + from_secret: github_token + note: CHANGELOG.md + overwrite: true + title: ${CI_COMMIT_TAG} + when: + - event: [tag] + +depends_on: + - test diff --git a/.woodpecker/build-container.yml b/.woodpecker/build-container.yml new file mode 100644 index 0000000..8f39dab --- /dev/null +++ b/.woodpecker/build-container.yml @@ -0,0 +1,66 @@ +--- +when: + - event: [pull_request, tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +steps: + dryrun: + image: quay.io/thegeeklab/wp-docker-buildx + settings: + containerfile: Containerfile.multiarch + dry_run: true + platforms: + - linux/amd64 + - linux/arm64 + provenance: false + repo: ${CI_REPO} + when: + - event: [pull_request] + + publish-dockerhub: + group: container + image: quay.io/thegeeklab/wp-docker-buildx + settings: + auto_tag: true + containerfile: Containerfile.multiarch + password: + from_secret: docker_password + platforms: + - linux/amd64 + - linux/arm64 + provenance: false + repo: ${CI_REPO} + username: + from_secret: docker_username + when: + - event: [tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + + publish-quay: + group: container + image: quay.io/thegeeklab/wp-docker-buildx + settings: + auto_tag: true + containerfile: Containerfile.multiarch + password: + from_secret: quay_password + platforms: + - linux/amd64 + - linux/arm64 + provenance: false + registry: quay.io + repo: quay.io/${CI_REPO} + username: + from_secret: quay_username + when: + - event: [tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +depends_on: + - test diff --git a/.woodpecker/docs.yml b/.woodpecker/docs.yml new file mode 100644 index 0000000..d3a5c80 --- /dev/null +++ b/.woodpecker/docs.yml @@ -0,0 +1,72 @@ +--- +when: + - event: [pull_request, tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +steps: + markdownlint: + image: quay.io/thegeeklab/markdownlint-cli + commands: + - markdownlint 'README.md' 'CONTRIBUTING.md' + + spellcheck: + image: quay.io/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" + + publish: + image: quay.io/thegeeklab/wp-git-action + settings: + action: + - pages + author_email: bot@thegeeklab.de + author_name: thegeeklab-bot + branch: docs + message: "[skip ci] auto-update documentation" + netrc_password: + from_secret: github_token + pages_directory: _docs/ + when: + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + + pushrm-dockerhub: + image: docker.io/chko/docker-pushrm:1 + secrets: + - source: docker_password + target: DOCKER_PASS + - source: docker_username + target: DOCKER_USER + environment: + PUSHRM_FILE: README.md + PUSHRM_SHORT: Woodpecker CI plugin to perform S3 actions + PUSHRM_TARGET: ${CI_REPO} + when: + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + status: [success] + + pushrm-quay: + image: docker.io/chko/docker-pushrm:1 + secrets: + - source: quay_token + target: APIKEY__QUAY_IO + environment: + PUSHRM_FILE: README.md + PUSHRM_TARGET: quay.io/${CI_REPO} + when: + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + status: [success] + +depends_on: + - build-binary + - build-container diff --git a/.woodpecker/notify.yml b/.woodpecker/notify.yml new file mode 100644 index 0000000..9028f78 --- /dev/null +++ b/.woodpecker/notify.yml @@ -0,0 +1,30 @@ +--- +when: + - event: [tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +runs_on: [success, failure] + +steps: + matrix: + image: quay.io/thegeeklab/drone-matrix + settings: + homeserver: + from_secret: matrix_homeserver + password: + from_secret: matrix_password + roomid: + from_secret: matrix_roomid + template: >- + Status: **{{ .Build.Status }}**
+ Build: [{{ .Repo.Owner }}/{{ .Repo.Name }}]({{ .Build.Link }}){{ if .Build.Branch }} ({{ .Build.Branch }}){{ end }} by {{ .Commit.Author }}
+ Message: {{ .Commit.Message.Title }} + username: + from_secret: matrix_username + when: + - status: [success, failure] + +depends_on: + - docs diff --git a/.woodpecker/test.yml b/.woodpecker/test.yml new file mode 100644 index 0000000..ce06663 --- /dev/null +++ b/.woodpecker/test.yml @@ -0,0 +1,22 @@ +--- +when: + - event: [pull_request, tag] + - event: [push, manual] + branch: + - ${CI_REPO_DEFAULT_BRANCH} + +steps: + deps: + image: docker.io/library/golang:1.21 + commands: + - make deps + + lint: + image: docker.io/library/golang:1.21 + commands: + - make lint + + test: + image: docker.io/library/golang:1.21 + commands: + - make test diff --git a/Dockerfile.multiarch b/Containerfile.multiarch similarity index 59% rename from Dockerfile.multiarch rename to Containerfile.multiarch index d25ee61..c829225 100644 --- a/Dockerfile.multiarch +++ b/Containerfile.multiarch @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1.20@sha256:839ba88412b5d3e12d66ed4774a85fc6e6c644dce8074ab82c798e5db27d4a09 as build +FROM --platform=$BUILDPLATFORM golang:1.21 as build ARG TARGETOS ARG TARGETARCH @@ -12,10 +12,10 @@ FROM alpine:3.18@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4 LABEL maintainer="Robert Kaussow " LABEL org.opencontainers.image.authors="Robert Kaussow " -LABEL org.opencontainers.image.title="drone-s3-sync" -LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-s3-sync" -LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-s3-sync" -LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-s3-sync" +LABEL org.opencontainers.image.title="wp-s3-action" +LABEL org.opencontainers.image.url="https://github.com/thegeeklab/wp-s3-action" +LABEL org.opencontainers.image.source="https://github.com/thegeeklab/wp-s3-action" +LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/wp-s3-action" -COPY --from=build /src/dist/drone-s3-sync /bin/drone-s3-sync -ENTRYPOINT ["/bin/drone-s3-sync"] +COPY --from=build /src/dist/wp-s3-action /bin/wp-s3-action +ENTRYPOINT ["/bin/wp-s3-action"] diff --git a/Makefile b/Makefile index d33df3c..1866cd3 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ GOFUMPT_PACKAGE_VERSION := v0.5.0 # renovate: datasource=github-releases depName=golangci/golangci-lint GOLANGCI_LINT_PACKAGE_VERSION := v1.54.1 -EXECUTABLE := drone-s3-sync +EXECUTABLE := wp-s3-action DIST := dist DIST_DIRS := $(DIST) @@ -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.21.x XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64 TARGETOS ?= linux @@ -30,8 +30,8 @@ endif TAGS ?= netgo,osusergo ifndef VERSION - ifneq ($(DRONE_TAG),) - VERSION ?= $(subst v,,$(DRONE_TAG)) + ifneq ($(CI_COMMIT_TAG),) + VERSION ?= $(subst v,,$(CI_COMMIT_TAG)) else VERSION ?= $(shell git rev-parse --short HEAD) endif diff --git a/README.md b/README.md index 891fb48..437f884 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,21 @@ -# drone-s3-sync +# wp-s3-action -Drone plugin to synchronize a directory with an S3 bucket +Woodpecker CI plugin to perform S3 actions -[![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) -[![Quay.io](https://img.shields.io/badge/quay-latest-blue.svg?logo=docker&logoColor=white)](https://quay.io/repository/thegeeklab/drone-s3-sync) -[![Go Report Card](https://goreportcard.com/badge/github.com/thegeeklab/drone-s3-sync)](https://goreportcard.com/report/github.com/thegeeklab/drone-s3-sync) -[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/drone-s3-sync)](https://github.com/thegeeklab/drone-s3-sync/graphs/contributors) -[![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) +[![Build Status](https://ci.thegeeklab.de/api/badges/thegeeklab/wp-s3-action/status.svg)](https://ci.thegeeklab.de/repos/thegeeklab/wp-s3-action) +[![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/wp-s3-action) +[![Quay.io](https://img.shields.io/badge/quay-latest-blue.svg?logo=docker&logoColor=white)](https://quay.io/repository/thegeeklab/wp-s3-action) +[![Go Report Card](https://goreportcard.com/badge/github.com/thegeeklab/wp-s3-action)](https://goreportcard.com/report/github.com/thegeeklab/wp-s3-action) +[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/wp-s3-action)](https://github.com/thegeeklab/wp-s3-action/graphs/contributors) +[![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/wp-s3-action) +[![License: MIT](https://img.shields.io/github/license/thegeeklab/wp-s3-action)](https://github.com/thegeeklab/wp-s3-action/blob/main/LICENSE) -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). +Woodpecker CI plugin to perform S3 actions. You can find the full documentation at [https://wp-plugin-index.geekdocs.de](https://wp-plugin-index.geekdocs.de/plugins/wp-s3-action). ## Contributors -Special thanks to all [contributors](https://github.com/thegeeklab/drone-s3-sync/graphs/contributors). If you would like to contribute, please see the [instructions](https://github.com/thegeeklab/drone-s3-sync/blob/main/CONTRIBUTING.md). +Special thanks to all [contributors](https://github.com/thegeeklab/wp-s3-action/graphs/contributors). If you would like to contribute, please see the [instructions](https://github.com/thegeeklab/wp-s3-action/blob/main/CONTRIBUTING.md). ## License -This project is licensed under the MIT License - see the [LICENSE](https://github.com/thegeeklab/drone-s3-sync/blob/main/LICENSE) file for details. +This project is licensed under the MIT License - see the [LICENSE](https://github.com/thegeeklab/wp-s3-action/blob/main/LICENSE) file for details. diff --git a/_docs/content/_index.md b/_docs/content/_index.md index ed61470..5a9f396 100644 --- a/_docs/content/_index.md +++ b/_docs/content/_index.md @@ -1,15 +1,16 @@ --- -title: drone-s3-sync +title: wp-s3-action --- -[![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) -[![Quay.io](https://img.shields.io/badge/quay-latest-blue.svg?logo=docker&logoColor=white)](https://quay.io/repository/thegeeklab/drone-s3-sync) -[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/drone-s3-sync)](https://github.com/thegeeklab/drone-s3-sync/graphs/contributors) -[![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) +[![Build Status](https://ci.thegeeklab.de/api/badges/thegeeklab/wp-s3-action/status.svg)](https://ci.thegeeklab.de/repos/thegeeklab/wp-s3-action) +[![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/wp-s3-action) +[![Quay.io](https://img.shields.io/badge/quay-latest-blue.svg?logo=docker&logoColor=white)](https://quay.io/repository/thegeeklab/wp-s3-action) +[![Go Report Card](https://goreportcard.com/badge/github.com/thegeeklab/wp-s3-action)](https://goreportcard.com/report/github.com/thegeeklab/wp-s3-action) +[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/wp-s3-action)](https://github.com/thegeeklab/wp-s3-action/graphs/contributors) +[![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/wp-s3-action) +[![License: MIT](https://img.shields.io/github/license/thegeeklab/wp-s3-action)](https://github.com/thegeeklab/wp-s3-action/blob/main/LICENSE) -Drone plugin to synchronize a directory with an S3 bucket. +Woodpecker CI plugin to perform S3 actions. @@ -25,7 +26,7 @@ name: default steps: - name: sync - image: thegeeklab/drone-s3-sync + image: thegeeklab/wp-s3-action settings: access_key: a50d28f4dd477bc184fbd10b376de753 secret_key: bc5785d3ece6a9cdefa42eb99b58986f9095ff1c @@ -39,7 +40,7 @@ steps: -{{< propertylist name=drone-s3-sync.data sort=name >}} +{{< propertylist name=wp-s3-action.data sort=name >}} @@ -53,7 +54,7 @@ name: default steps: - name: sync - image: thegeeklab/drone-s3-sync + image: thegeeklab/wp-s3-action settings: access_key: a50d28f4dd477bc184fbd10b376de753 secret_key: bc5785d3ece6a9cdefa42eb99b58986f9095ff1c @@ -89,7 +90,7 @@ name: default steps: - name: sync - image: thegeeklab/drone-s3-sync + image: thegeeklab/wp-s3-action settings: endpoint: https://minio.example.com access_key: a50d28f4dd477bc184fbd10b376de753 @@ -105,18 +106,13 @@ steps: Build the binary with the following command: ```Shell -export GOOS=linux -export GOARCH=amd64 -export CGO_ENABLED=0 -export GO111MODULE=on - make build ``` -Build the Docker image with the following command: +Build the container image with the following command: ```Shell -docker build --file docker/Dockerfile.amd64 --tag thegeeklab/drone-s3-sync . +docker build --file Containerfile.multiarch --tag thegeeklab/wp-s3-action . ``` ## Test @@ -126,7 +122,7 @@ docker run --rm \ -e PLUGIN_BUCKET=my_bucket \ -e AWS_ACCESS_KEY_ID=abc123 \ -e AWS_SECRET_ACCESS_KEY=xyc789 \ - -v $(pwd):$(pwd) \ - -w $(pwd) \ - thegeeklab/drone-s3-sync + -v $(pwd):/build:z \ + -w /build \ + thegeeklab/wp-s3-action ``` diff --git a/cmd/drone-s3-sync/main.go b/cmd/drone-s3-sync/main.go deleted file mode 100644 index 0057979..0000000 --- a/cmd/drone-s3-sync/main.go +++ /dev/null @@ -1,104 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "os" - - "github.com/joho/godotenv" - "github.com/sirupsen/logrus" - "github.com/thegeeklab/drone-plugin-lib/v2/urfave" - "github.com/thegeeklab/drone-s3-sync/plugin" - "github.com/urfave/cli/v2" -) - -//nolint:gochecknoglobals -var ( - BuildVersion = "devel" - BuildDate = "00000000" -) - -var ErrTypeAssertionFailed = errors.New("type assertion failed") - -func main() { - settings := &plugin.Settings{} - - if _, err := os.Stat("/run/drone/env"); err == nil { - _ = godotenv.Overload("/run/drone/env") - } - - cli.VersionPrinter = func(c *cli.Context) { - fmt.Printf("%s version=%s date=%s\n", c.App.Name, c.App.Version, BuildDate) - } - - app := &cli.App{ - Name: "drone-s3-sync", - Usage: "synchronize a directory with an S3 bucket", - Version: BuildVersion, - Flags: append(settingsFlags(settings, urfave.FlagsPluginCategory), urfave.Flags()...), - Action: run(settings), - } - - if err := app.Run(os.Args); err != nil { - logrus.Fatal(err) - } -} - -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() - - plugin := plugin.New( - *settings, - urfave.PipelineFromContext(ctx), - urfave.NetworkFromContext(ctx), - ) - - if err := plugin.Validate(); err != nil { - return fmt.Errorf("validation failed: %w", err) - } - - if err := plugin.Execute(); err != nil { - return fmt.Errorf("execution failed: %w", err) - } - - return nil - } -} diff --git a/cmd/drone-s3-sync/types.go b/cmd/drone-s3-sync/types.go deleted file mode 100644 index a4bfdb9..0000000 --- a/cmd/drone-s3-sync/types.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "encoding/json" -) - -type DeepStringMapFlag struct { - parts map[string]map[string]string -} - -func (d *DeepStringMapFlag) String() string { - return "" -} - -func (d *DeepStringMapFlag) Get() map[string]map[string]string { - return d.parts -} - -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 - } - - d.parts["*"] = single - } - - return nil -} - -type StringMapFlag struct { - parts map[string]string -} - -func (s *StringMapFlag) String() string { - return "" -} - -func (s *StringMapFlag) Get() map[string]string { - return s.parts -} - -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 -} - -type MapFlag struct { - parts map[string]string -} - -func (m *MapFlag) String() string { - return "" -} - -func (m *MapFlag) Get() map[string]string { - return m.parts -} - -func (m *MapFlag) Set(value string) error { - m.parts = map[string]string{} - - return json.Unmarshal([]byte(value), &m.parts) -} diff --git a/cmd/drone-s3-sync/config.go b/cmd/wp-s3-action/config.go similarity index 72% rename from cmd/drone-s3-sync/config.go rename to cmd/wp-s3-action/config.go index ed62955..82d13b2 100644 --- a/cmd/drone-s3-sync/config.go +++ b/cmd/wp-s3-action/config.go @@ -1,7 +1,8 @@ package main import ( - "github.com/thegeeklab/drone-s3-sync/plugin" + "github.com/thegeeklab/wp-s3-action/plugin" + "github.com/urfave/cli/v2" ) @@ -78,46 +79,46 @@ func settingsFlags(settings *plugin.Settings, category string) []cli.Flag { Category: category, }, &cli.GenericFlag{ - Name: "acl", - Usage: "access control list", - EnvVars: []string{"PLUGIN_ACL"}, - Value: &StringMapFlag{}, - Category: category, + Name: "acl", + Usage: "access control list", + EnvVars: []string{"PLUGIN_ACL"}, + Destination: &settings.ACL, + Category: category, }, &cli.GenericFlag{ - Name: "content-type", - Usage: "content-type settings for uploads", - EnvVars: []string{"PLUGIN_CONTENT_TYPE"}, - Value: &StringMapFlag{}, - Category: category, + Name: "content-type", + Usage: "content-type settings for uploads", + EnvVars: []string{"PLUGIN_CONTENT_TYPE"}, + Destination: &settings.ContentType, + Category: category, }, &cli.GenericFlag{ - Name: "content-encoding", - Usage: "content-encoding settings for uploads", - EnvVars: []string{"PLUGIN_CONTENT_ENCODING"}, - Value: &StringMapFlag{}, - Category: category, + Name: "content-encoding", + Usage: "content-encoding settings for uploads", + EnvVars: []string{"PLUGIN_CONTENT_ENCODING"}, + Destination: &settings.ContentEncoding, + Category: category, }, &cli.GenericFlag{ - Name: "cache-control", - Usage: "cache-control settings for uploads", - EnvVars: []string{"PLUGIN_CACHE_CONTROL"}, - Value: &StringMapFlag{}, - Category: category, + Name: "cache-control", + Usage: "cache-control settings for uploads", + EnvVars: []string{"PLUGIN_CACHE_CONTROL"}, + Destination: &settings.CacheControl, + Category: category, }, &cli.GenericFlag{ - Name: "metadata", - Usage: "additional metadata for uploads", - EnvVars: []string{"PLUGIN_METADATA"}, - Value: &DeepStringMapFlag{}, - Category: category, + Name: "metadata", + Usage: "additional metadata for uploads", + EnvVars: []string{"PLUGIN_METADATA"}, + Destination: &settings.Metadata, + Category: category, }, &cli.GenericFlag{ - Name: "redirects", - Usage: "redirects to create", - EnvVars: []string{"PLUGIN_REDIRECTS"}, - Value: &MapFlag{}, - Category: category, + Name: "redirects", + Usage: "redirects to create", + EnvVars: []string{"PLUGIN_REDIRECTS"}, + Destination: &settings.Redirects, + Category: category, }, &cli.StringFlag{ Name: "cloudfront-distribution", diff --git a/cmd/wp-s3-action/main.go b/cmd/wp-s3-action/main.go new file mode 100644 index 0000000..fb0d402 --- /dev/null +++ b/cmd/wp-s3-action/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "fmt" + + "github.com/thegeeklab/wp-s3-action/plugin" + + wp "github.com/thegeeklab/wp-plugin-go/plugin" +) + +//nolint:gochecknoglobals +var ( + BuildVersion = "devel" + BuildDate = "00000000" +) + +func main() { + settings := &plugin.Settings{} + options := wp.Options{ + Name: "wp-s3-action", + Description: "Perform S3 actions", + Version: BuildVersion, + VersionMetadata: fmt.Sprintf("date=%s", BuildDate), + Flags: settingsFlags(settings, wp.FlagsPluginCategory), + } + + plugin.New(options, settings).Run() +} diff --git a/go.mod b/go.mod index fffb31a..941ff57 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,24 @@ -module github.com/thegeeklab/drone-s3-sync +module github.com/thegeeklab/wp-s3-action -go 1.20 +go 1.21 require ( github.com/aws/aws-sdk-go v1.44.302 - github.com/joho/godotenv v1.5.1 + github.com/rs/zerolog v1.30.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/thegeeklab/wp-plugin-go v0.4.0 github.com/urfave/cli/v2 v2.25.7 ) require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // 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/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index 46c0b73..34171a0 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,35 @@ 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/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= 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/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 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= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 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/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/thegeeklab/wp-plugin-go v0.4.0 h1:eTkRH04gAAsYgCUekk8RBmPrIXk+UG+EJtRkoUFllLs= +github.com/thegeeklab/wp-plugin-go v0.4.0/go.mod h1:y0k5zaKWjdGbgkaOHhEPFEL6p+yOLOjqHy0LWOrv0MM= 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/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= @@ -36,27 +41,29 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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/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/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.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= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -64,5 +71,3 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/plugin/aws.go b/plugin/aws.go index db0a47c..0cdffb5 100644 --- a/plugin/aws.go +++ b/plugin/aws.go @@ -18,8 +18,8 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/cloudfront" "github.com/aws/aws-sdk-go/service/s3" + "github.com/rs/zerolog/log" "github.com/ryanuber/go-glob" - "github.com/sirupsen/logrus" ) type AWS struct { @@ -32,18 +32,18 @@ type AWS struct { func NewAWS(plugin *Plugin) AWS { sessCfg := &aws.Config{ - S3ForcePathStyle: aws.Bool(plugin.settings.PathStyle), - Region: aws.String(plugin.settings.Region), + S3ForcePathStyle: aws.Bool(plugin.Settings.PathStyle), + Region: aws.String(plugin.Settings.Region), } - if plugin.settings.Endpoint != "" { - sessCfg.Endpoint = &plugin.settings.Endpoint - sessCfg.DisableSSL = aws.Bool(strings.HasPrefix(plugin.settings.Endpoint, "http://")) + if plugin.Settings.Endpoint != "" { + sessCfg.Endpoint = &plugin.Settings.Endpoint + sessCfg.DisableSSL = aws.Bool(strings.HasPrefix(plugin.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 plugin.Settings.AccessKey != "" && plugin.Settings.SecretKey != "" { + sessCfg.Credentials = credentials.NewStaticCredentials(plugin.Settings.AccessKey, plugin.Settings.SecretKey, "") } sess, _ := session.NewSession(sessCfg) @@ -73,9 +73,9 @@ func (a *AWS) Upload(local, remote string) error { var acl string - for pattern := range plugin.settings.ACL { + for pattern := range plugin.Settings.ACL.Get() { if match := glob.Glob(pattern, local); match { - acl = plugin.settings.ACL[pattern] + acl = plugin.Settings.ACL.Get()[pattern] break } @@ -89,9 +89,9 @@ func (a *AWS) Upload(local, remote string) error { var contentType string - for patternExt := range plugin.settings.ContentType { + for patternExt := range plugin.Settings.ContentType.Get() { if patternExt == fileExt { - contentType = plugin.settings.ContentType[patternExt] + contentType = plugin.Settings.ContentType.Get()[patternExt] break } @@ -103,9 +103,9 @@ func (a *AWS) Upload(local, remote string) error { var contentEncoding string - for patternExt := range plugin.settings.ContentEncoding { + for patternExt := range plugin.Settings.ContentEncoding.Get() { if patternExt == fileExt { - contentEncoding = plugin.settings.ContentEncoding[patternExt] + contentEncoding = plugin.Settings.ContentEncoding.Get()[patternExt] break } @@ -113,9 +113,9 @@ func (a *AWS) Upload(local, remote string) error { var cacheControl string - for pattern := range plugin.settings.CacheControl { + for pattern := range plugin.Settings.CacheControl.Get() { if match := glob.Glob(pattern, local); match { - cacheControl = plugin.settings.CacheControl[pattern] + cacheControl = plugin.Settings.CacheControl.Get()[pattern] break } @@ -123,9 +123,9 @@ func (a *AWS) Upload(local, remote string) error { metadata := map[string]*string{} - for pattern := range plugin.settings.Metadata { + for pattern := range plugin.Settings.Metadata.Get() { if match := glob.Glob(pattern, local); match { - for k, v := range plugin.settings.Metadata[pattern] { + for k, v := range plugin.Settings.Metadata.Get()[pattern] { metadata[k] = aws.String(v) } @@ -136,7 +136,7 @@ func (a *AWS) Upload(local, remote string) error { var AWSErr awserr.Error head, err := a.client.HeadObject(&s3.HeadObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(remote), }) if err != nil && errors.As(err, &AWSErr) { @@ -145,7 +145,7 @@ func (a *AWS) Upload(local, remote string) error { return err } - logrus.Debugf( + log.Debug().Msgf( "'%s' not found in bucket, uploading with content-type '%s' and permissions '%s'", local, contentType, @@ -153,7 +153,7 @@ func (a *AWS) Upload(local, remote string) error { ) putObject := &s3.PutObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(remote), Body: file, ContentType: aws.String(contentType), @@ -170,7 +170,7 @@ func (a *AWS) Upload(local, remote string) error { } // skip upload during dry run - if a.plugin.settings.DryRun { + if a.plugin.Settings.DryRun { return nil } @@ -189,43 +189,43 @@ func (a *AWS) Upload(local, remote string) error { shouldCopy := false if head.ContentType == nil && contentType != "" { - logrus.Debugf("content-type has changed from unset to %s", contentType) + log.Debug().Msgf("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) + log.Debug().Msgf("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) + log.Debug().Msgf("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) + log.Debug().Msgf("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) + log.Debug().Msgf("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) + log.Debug().Msgf("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) + log.Debug().Msgf("count of metadata values has changed for %s", local) shouldCopy = true } @@ -234,7 +234,7 @@ func (a *AWS) Upload(local, remote string) error { for k, v := range metadata { if hv, ok := head.Metadata[k]; ok { if *v != *hv { - logrus.Debugf("metadata values have changed for %s", local) + log.Debug().Msgf("metadata values have changed for %s", local) shouldCopy = true @@ -246,7 +246,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(plugin.Settings.Bucket), Key: aws.String(remote), }) if err != nil { @@ -275,24 +275,24 @@ 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) + log.Debug().Msgf("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) + log.Debug().Msgf("skipping '%s' because hashes and metadata match", local) return nil } - logrus.Debugf("updating metadata for '%s' content-type: '%s', ACL: '%s'", local, contentType, acl) + log.Debug().Msgf("updating metadata for '%s' content-type: '%s', ACL: '%s'", local, contentType, acl) copyObject := &s3.CopyObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(remote), - CopySource: aws.String(fmt.Sprintf("%s/%s", plugin.settings.Bucket, remote)), + CopySource: aws.String(fmt.Sprintf("%s/%s", plugin.Settings.Bucket, remote)), ACL: aws.String(acl), ContentType: aws.String(contentType), Metadata: metadata, @@ -308,7 +308,7 @@ func (a *AWS) Upload(local, remote string) error { } // skip update if dry run - if a.plugin.settings.DryRun { + if a.plugin.Settings.DryRun { return nil } @@ -322,10 +322,10 @@ func (a *AWS) Upload(local, remote string) error { return err } - logrus.Debugf("uploading '%s' with content-type '%s' and permissions '%s'", local, contentType, acl) + log.Debug().Msgf("uploading '%s' with content-type '%s' and permissions '%s'", local, contentType, acl) putObject := &s3.PutObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(remote), Body: file, ContentType: aws.String(contentType), @@ -342,7 +342,7 @@ func (a *AWS) Upload(local, remote string) error { } // skip upload if dry run - if a.plugin.settings.DryRun { + if a.plugin.Settings.DryRun { return nil } @@ -354,14 +354,14 @@ func (a *AWS) Upload(local, remote string) error { func (a *AWS) Redirect(path, location string) error { plugin := a.plugin - logrus.Debugf("adding redirect from '%s' to '%s'", path, location) + log.Debug().Msgf("adding redirect from '%s' to '%s'", path, location) - if a.plugin.settings.DryRun { + if a.plugin.Settings.DryRun { return nil } _, err := a.client.PutObject(&s3.PutObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(path), ACL: aws.String("public-read"), WebsiteRedirectLocation: aws.String(location), @@ -373,14 +373,14 @@ func (a *AWS) Redirect(path, location string) error { func (a *AWS) Delete(remote string) error { plugin := a.plugin - logrus.Debugf("removing remote file '%s'", remote) + log.Debug().Msgf("removing remote file '%s'", remote) - if a.plugin.settings.DryRun { + if a.plugin.Settings.DryRun { return nil } _, err := a.client.DeleteObject(&s3.DeleteObjectInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Key: aws.String(remote), }) @@ -393,7 +393,7 @@ func (a *AWS) List(path string) ([]string, error) { remote := make([]string, 0) resp, err := a.client.ListObjects(&s3.ListObjectsInput{ - Bucket: aws.String(plugin.settings.Bucket), + Bucket: aws.String(plugin.Settings.Bucket), Prefix: aws.String(path), }) if err != nil { @@ -406,7 +406,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(plugin.Settings.Bucket), Prefix: aws.String(path), Marker: aws.String(remote[len(remote)-1]), }) @@ -426,10 +426,10 @@ func (a *AWS) List(path string) ([]string, error) { func (a *AWS) Invalidate(invalidatePath string) error { p := a.plugin - logrus.Debugf("invalidating '%s'", invalidatePath) + log.Debug().Msgf("invalidating '%s'", invalidatePath) _, err := a.cfClient.CreateInvalidation(&cloudfront.CreateInvalidationInput{ - DistributionId: aws.String(p.settings.CloudFrontDistribution), + DistributionId: aws.String(p.Settings.CloudFrontDistribution), InvalidationBatch: &cloudfront.InvalidationBatch{ CallerReference: aws.String(time.Now().Format(time.RFC3339Nano)), Paths: &cloudfront.Paths{ diff --git a/plugin/impl.go b/plugin/impl.go index fe40b50..033d734 100644 --- a/plugin/impl.go +++ b/plugin/impl.go @@ -1,47 +1,32 @@ package plugin import ( + "context" + "errors" "fmt" "os" "path/filepath" "strings" - "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" + "github.com/urfave/cli/v2" ) -// Settings for the Plugin. -type Settings struct { - Endpoint string - AccessKey string - SecretKey string - Bucket string - Region string - Source string - Target string - Delete bool - ACL map[string]string - CacheControl map[string]string - ContentType map[string]string - ContentEncoding map[string]string - Metadata map[string]map[string]string - Redirects map[string]string - CloudFrontDistribution string - DryRun bool - PathStyle bool - Client AWS - Jobs []Job - MaxConcurrency int -} +var ErrTypeAssertionFailed = errors.New("type assertion failed") -type Job struct { - local string - remote string - action string -} +// Execute provides the implementation of the plugin. +// +//nolint:revive +func (p *Plugin) run(ctx context.Context, cCtx *cli.Context) error { + if err := p.Validate(); err != nil { + return fmt.Errorf("validation failed: %w", err) + } -type Result struct { - j Job - err error + if err := p.Execute(); err != nil { + return fmt.Errorf("execution failed: %w", err) + } + + return nil } // Validate handles the settings validation of the plugin. @@ -51,25 +36,25 @@ func (p *Plugin) Validate() error { 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, "/") + p.Settings.Source = filepath.Join(wd, p.Settings.Source) + p.Settings.Target = strings.TrimPrefix(p.Settings.Target, "/") return nil } // Execute provides the implementation of the plugin. func (p *Plugin) Execute() error { - p.settings.Jobs = make([]Job, 1) - p.settings.Client = NewAWS(p) + p.Settings.Jobs = make([]Job, 1) + p.Settings.Client = NewAWS(p) if err := p.createSyncJobs(); err != nil { return fmt.Errorf("error while creating sync job: %w", err) } - if len(p.settings.CloudFrontDistribution) > 0 { - p.settings.Jobs = append(p.settings.Jobs, Job{ + if len(p.Settings.CloudFrontDistribution) > 0 { + p.Settings.Jobs = append(p.Settings.Jobs, Job{ local: "", - remote: filepath.Join("/", p.settings.Target, "*"), + remote: filepath.Join("/", p.Settings.Target, "*"), action: "invalidateCloudFront", }) } @@ -82,27 +67,27 @@ func (p *Plugin) Execute() error { } func (p *Plugin) createSyncJobs() error { - remote, err := p.settings.Client.List(p.settings.Target) + remote, err := p.Settings.Client.List(p.Settings.Target) if err != nil { return err } local := make([]string, 0) - err = filepath.Walk(p.settings.Source, func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(p.Settings.Source, func(path string, info os.FileInfo, err error) error { if err != nil || info.IsDir() { return err } localPath := path - if p.settings.Source != "." { - localPath = strings.TrimPrefix(path, p.settings.Source) + if p.Settings.Source != "." { + localPath = strings.TrimPrefix(path, p.Settings.Source) localPath = strings.TrimPrefix(localPath, "/") } local = append(local, localPath) - p.settings.Jobs = append(p.settings.Jobs, Job{ - local: filepath.Join(p.settings.Source, localPath), - remote: filepath.Join(p.settings.Target, localPath), + p.Settings.Jobs = append(p.Settings.Jobs, Job{ + local: filepath.Join(p.Settings.Source, localPath), + remote: filepath.Join(p.Settings.Target, localPath), action: "upload", }) @@ -112,20 +97,20 @@ func (p *Plugin) createSyncJobs() error { return err } - for path, location := range p.settings.Redirects { + for path, location := range p.Settings.Redirects.Get() { path = strings.TrimPrefix(path, "/") local = append(local, path) - p.settings.Jobs = append(p.settings.Jobs, Job{ + p.Settings.Jobs = append(p.Settings.Jobs, Job{ local: path, remote: location, action: "redirect", }) } - if p.settings.Delete { + if p.Settings.Delete { for _, remote := range remote { found := false - remotePath := strings.TrimPrefix(remote, p.settings.Target+"/") + remotePath := strings.TrimPrefix(remote, p.Settings.Target+"/") for _, l := range local { if l == remotePath { @@ -136,7 +121,7 @@ func (p *Plugin) createSyncJobs() error { } if !found { - p.settings.Jobs = append(p.settings.Jobs, Job{ + p.Settings.Jobs = append(p.Settings.Jobs, Job{ local: "", remote: remote, action: "delete", @@ -149,15 +134,15 @@ func (p *Plugin) createSyncJobs() error { } func (p *Plugin) runJobs() error { - client := p.settings.Client - jobChan := make(chan struct{}, p.settings.MaxConcurrency) - results := make(chan *Result, len(p.settings.Jobs)) + 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) + log.Info().Msgf("Synchronizing with bucket '%s'", p.Settings.Bucket) - for _, job := range p.settings.Jobs { + for _, job := range p.Settings.Jobs { jobChan <- struct{}{} go func(job Job) { @@ -181,7 +166,7 @@ func (p *Plugin) runJobs() error { }(job) } - for range p.settings.Jobs { + 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) diff --git a/plugin/plugin.go b/plugin/plugin.go index 85551fc..d595280 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -1,21 +1,58 @@ package plugin import ( - "github.com/thegeeklab/drone-plugin-lib/v2/drone" + wp "github.com/thegeeklab/wp-plugin-go/plugin" + "github.com/thegeeklab/wp-plugin-go/types" ) -// Plugin implements drone.Plugin to provide the plugin implementation. +// Plugin implements provide the plugin implementation. type Plugin struct { - settings Settings - pipeline drone.Pipeline - network drone.Network + *wp.Plugin + Settings *Settings } -// New initializes a plugin from the given Settings, Pipeline, and Network. -func New(settings Settings, pipeline drone.Pipeline, network drone.Network) *Plugin { - return &Plugin{ - settings: settings, - pipeline: pipeline, - network: network, - } +// Settings for the Plugin. +type Settings struct { + Endpoint string + AccessKey string + SecretKey string + Bucket string + Region string + Source string + Target string + Delete bool + ACL types.StringMapFlag + CacheControl types.StringMapFlag + ContentType types.StringMapFlag + ContentEncoding types.StringMapFlag + Metadata types.DeepStringMapFlag + Redirects types.StringMapFlag + CloudFrontDistribution string + DryRun bool + PathStyle bool + Client AWS + Jobs []Job + MaxConcurrency int +} + +type Job struct { + local string + remote string + action string +} + +type Result struct { + j Job + err error +} + +func New(options wp.Options, settings *Settings) *Plugin { + p := &Plugin{} + + options.Execute = p.run + + p.Plugin = wp.New(options) + p.Settings = settings + + return p }