mirror of
https://github.com/thegeeklab/drone-docker.git
synced 2024-11-23 13:20:40 +00:00
fork: initial commit
This commit is contained in:
commit
f9e5a49b33
322
.drone.jsonnet
Normal file
322
.drone.jsonnet
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
local PipelineTest = {
|
||||||
|
kind: 'pipeline',
|
||||||
|
image_pull_secrets: ['docker_config'],
|
||||||
|
name: 'test',
|
||||||
|
platform: {
|
||||||
|
os: 'linux',
|
||||||
|
arch: 'amd64',
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
name: 'staticcheck',
|
||||||
|
image: 'golang:1.15',
|
||||||
|
commands: [
|
||||||
|
'go run honnef.co/go/tools/cmd/staticcheck ./...',
|
||||||
|
],
|
||||||
|
volumes: [
|
||||||
|
{
|
||||||
|
name: 'gopath',
|
||||||
|
path: '/go',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'lint',
|
||||||
|
image: 'golang:1.15',
|
||||||
|
commands: [
|
||||||
|
'go run golang.org/x/lint/golint -set_exit_status ./...',
|
||||||
|
],
|
||||||
|
volumes: [
|
||||||
|
{
|
||||||
|
name: 'gopath',
|
||||||
|
path: '/go',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vet',
|
||||||
|
image: 'golang:1.15',
|
||||||
|
commands: [
|
||||||
|
'go vet ./...',
|
||||||
|
],
|
||||||
|
volumes: [
|
||||||
|
{
|
||||||
|
name: 'gopath',
|
||||||
|
path: '/go',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
image: 'golang:1.15',
|
||||||
|
commands: [
|
||||||
|
'go test -cover ./...',
|
||||||
|
],
|
||||||
|
volumes: [
|
||||||
|
{
|
||||||
|
name: 'gopath',
|
||||||
|
path: '/go',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
volumes: [
|
||||||
|
{
|
||||||
|
name: 'gopath',
|
||||||
|
temp: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
trigger: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
local PipelineBuildBinaries = {
|
||||||
|
kind: 'pipeline',
|
||||||
|
image_pull_secrets: ['docker_config'],
|
||||||
|
name: 'build-binaries',
|
||||||
|
platform: {
|
||||||
|
os: 'linux',
|
||||||
|
arch: 'amd64',
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
name: 'build',
|
||||||
|
image: 'techknowlogick/xgo:go-1.15.x',
|
||||||
|
commands: [
|
||||||
|
'[ -z "${DRONE_TAG}" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}',
|
||||||
|
'mkdir -p release/',
|
||||||
|
"cd cmd/drone-docker && xgo -ldflags \"-s -w -X main.version=$BUILD_VERSION\" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm64' -out drone-docker .",
|
||||||
|
'mv /build/* /drone/src/release/',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'executable',
|
||||||
|
image: 'alpine',
|
||||||
|
commands: [
|
||||||
|
'$(find release/ -executable -type f | grep drone-docker-linux-amd64) --help',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'compress',
|
||||||
|
image: 'alpine',
|
||||||
|
commands: [
|
||||||
|
'apk add upx',
|
||||||
|
'find release/ -maxdepth 1 -executable -type f -exec upx {} \\;',
|
||||||
|
'ls -lh release/',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'checksum',
|
||||||
|
image: 'alpine',
|
||||||
|
commands: [
|
||||||
|
'cd release/ && sha256sum * > sha256sum.txt',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'publish',
|
||||||
|
image: 'plugins/github-release',
|
||||||
|
settings: {
|
||||||
|
overwrite: true,
|
||||||
|
api_key: {
|
||||||
|
from_secret: 'github_token',
|
||||||
|
},
|
||||||
|
files: ['release/*'],
|
||||||
|
title: '${DRONE_TAG}',
|
||||||
|
note: 'CHANGELOG.md',
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
ref: [
|
||||||
|
'refs/tags/**',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
depends_on: [
|
||||||
|
'test',
|
||||||
|
],
|
||||||
|
trigger: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
local PipelineBuildContainer(arch='amd64') = {
|
||||||
|
kind: 'pipeline',
|
||||||
|
image_pull_secrets: ['docker_config'],
|
||||||
|
name: 'build-container-' + arch,
|
||||||
|
platform: {
|
||||||
|
os: 'linux',
|
||||||
|
arch: arch,
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
name: 'build',
|
||||||
|
image: 'golang:1.15',
|
||||||
|
commands: [
|
||||||
|
'[ -z "${DRONE_TAG}" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}',
|
||||||
|
'go build -v -ldflags "-X main.version=$BUILD_VERSION" -a -tags netgo -o release/' + arch + '/drone-docker ./cmd/drone-docker',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dryrun',
|
||||||
|
image: 'plugins/docker:19',
|
||||||
|
settings: {
|
||||||
|
config: { from_secret: 'docker_config' },
|
||||||
|
dry_run: true,
|
||||||
|
dockerfile: 'docker/Dockerfile.' + arch,
|
||||||
|
repo: 'thegeeklab/${DRONE_REPO_NAME}',
|
||||||
|
username: { from_secret: 'docker_username' },
|
||||||
|
password: { from_secret: 'docker_password' },
|
||||||
|
},
|
||||||
|
depends_on: ['build'],
|
||||||
|
when: {
|
||||||
|
ref: ['refs/pull/**'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'publish-dockerhub',
|
||||||
|
image: 'plugins/docker:19',
|
||||||
|
settings: {
|
||||||
|
config: { from_secret: 'docker_config' },
|
||||||
|
auto_tag: true,
|
||||||
|
auto_tag_suffix: arch,
|
||||||
|
dockerfile: 'docker/Dockerfile.' + arch,
|
||||||
|
repo: 'thegeeklab/${DRONE_REPO_NAME}',
|
||||||
|
username: { from_secret: 'docker_username' },
|
||||||
|
password: { from_secret: 'docker_password' },
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**'],
|
||||||
|
},
|
||||||
|
depends_on: ['dryrun'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'publish-quay',
|
||||||
|
image: 'plugins/docker:19',
|
||||||
|
settings: {
|
||||||
|
config: { from_secret: 'docker_config' },
|
||||||
|
auto_tag: true,
|
||||||
|
auto_tag_suffix: arch,
|
||||||
|
dockerfile: 'docker/Dockerfile.' + arch,
|
||||||
|
registry: 'quay.io',
|
||||||
|
repo: 'quay.io/thegeeklab/${DRONE_REPO_NAME}',
|
||||||
|
username: { from_secret: 'quay_username' },
|
||||||
|
password: { from_secret: 'quay_password' },
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**'],
|
||||||
|
},
|
||||||
|
depends_on: ['dryrun'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
depends_on: [
|
||||||
|
'test',
|
||||||
|
],
|
||||||
|
trigger: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
local PipelineNotifications = {
|
||||||
|
kind: 'pipeline',
|
||||||
|
image_pull_secrets: ['docker_config'],
|
||||||
|
name: 'notifications',
|
||||||
|
platform: {
|
||||||
|
os: 'linux',
|
||||||
|
arch: 'amd64',
|
||||||
|
},
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
image: 'plugins/manifest',
|
||||||
|
name: 'manifest-dockerhub',
|
||||||
|
settings: {
|
||||||
|
ignore_missing: true,
|
||||||
|
auto_tag: true,
|
||||||
|
username: { from_secret: 'docker_username' },
|
||||||
|
password: { from_secret: 'docker_password' },
|
||||||
|
spec: 'docker/manifest.tmpl',
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
status: ['success'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: 'plugins/manifest',
|
||||||
|
name: 'manifest-quay',
|
||||||
|
settings: {
|
||||||
|
ignore_missing: true,
|
||||||
|
auto_tag: true,
|
||||||
|
username: { from_secret: 'quay_username' },
|
||||||
|
password: { from_secret: 'quay_password' },
|
||||||
|
spec: 'docker/manifest-quay.tmpl',
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
status: ['success'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 build multiarch Docker images',
|
||||||
|
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: 'plugins/matrix',
|
||||||
|
settings: {
|
||||||
|
homeserver: { from_secret: 'matrix_homeserver' },
|
||||||
|
roomid: { from_secret: 'matrix_roomid' },
|
||||||
|
template: 'Status: **{{ build.status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.link }}) ({{ build.branch }}) by {{ build.author }}<br/> Message: {{ build.message }}',
|
||||||
|
username: { from_secret: 'matrix_username' },
|
||||||
|
password: { from_secret: 'matrix_password' },
|
||||||
|
},
|
||||||
|
when: {
|
||||||
|
status: ['success', 'failure'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
depends_on: [
|
||||||
|
'build-binaries',
|
||||||
|
'build-container-amd64',
|
||||||
|
'build-container-arm64',
|
||||||
|
],
|
||||||
|
trigger: {
|
||||||
|
ref: ['refs/heads/main', 'refs/tags/**'],
|
||||||
|
status: ['success', 'failure'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
PipelineTest,
|
||||||
|
PipelineBuildBinaries,
|
||||||
|
PipelineBuildContainer(arch='amd64'),
|
||||||
|
PipelineBuildContainer(arch='arm64'),
|
||||||
|
PipelineNotifications,
|
||||||
|
]
|
382
.drone.yml
Normal file
382
.drone.yml
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: test
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: amd64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: staticcheck
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- go run honnef.co/go/tools/cmd/staticcheck ./...
|
||||||
|
volumes:
|
||||||
|
- name: gopath
|
||||||
|
path: /go
|
||||||
|
|
||||||
|
- name: lint
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- go run golang.org/x/lint/golint -set_exit_status ./...
|
||||||
|
volumes:
|
||||||
|
- name: gopath
|
||||||
|
path: /go
|
||||||
|
|
||||||
|
- name: vet
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- go vet ./...
|
||||||
|
volumes:
|
||||||
|
- name: gopath
|
||||||
|
path: /go
|
||||||
|
|
||||||
|
- name: test
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- go test -cover ./...
|
||||||
|
volumes:
|
||||||
|
- name: gopath
|
||||||
|
path: /go
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: gopath
|
||||||
|
temp: {}
|
||||||
|
|
||||||
|
image_pull_secrets:
|
||||||
|
- docker_config
|
||||||
|
|
||||||
|
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.15.x
|
||||||
|
commands:
|
||||||
|
- "[ -z \"${DRONE_TAG}\" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}"
|
||||||
|
- mkdir -p release/
|
||||||
|
- cd cmd/drone-docker && xgo -ldflags "-s -w -X main.version=$BUILD_VERSION" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm64' -out drone-docker .
|
||||||
|
- mv /build/* /drone/src/release/
|
||||||
|
|
||||||
|
- name: executable
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- $(find release/ -executable -type f | grep drone-docker-linux-amd64) --help
|
||||||
|
|
||||||
|
- name: compress
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- apk add upx
|
||||||
|
- find release/ -maxdepth 1 -executable -type f -exec upx {} \;
|
||||||
|
- ls -lh release/
|
||||||
|
|
||||||
|
- name: checksum
|
||||||
|
image: alpine
|
||||||
|
commands:
|
||||||
|
- cd release/ && sha256sum * > sha256sum.txt
|
||||||
|
|
||||||
|
- name: publish
|
||||||
|
image: plugins/github-release
|
||||||
|
settings:
|
||||||
|
api_key:
|
||||||
|
from_secret: github_token
|
||||||
|
files:
|
||||||
|
- release/*
|
||||||
|
note: CHANGELOG.md
|
||||||
|
overwrite: true
|
||||||
|
title: ${DRONE_TAG}
|
||||||
|
when:
|
||||||
|
ref:
|
||||||
|
- refs/tags/**
|
||||||
|
|
||||||
|
image_pull_secrets:
|
||||||
|
- docker_config
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
- refs/pull/**
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- test
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: build-container-amd64
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: amd64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- "[ -z \"${DRONE_TAG}\" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}"
|
||||||
|
- go build -v -ldflags "-X main.version=$BUILD_VERSION" -a -tags netgo -o release/amd64/drone-docker ./cmd/drone-docker
|
||||||
|
|
||||||
|
- name: dryrun
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.amd64
|
||||||
|
dry_run: true
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: thegeeklab/${DRONE_REPO_NAME}
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
when:
|
||||||
|
ref:
|
||||||
|
- refs/pull/**
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
|
- name: publish-dockerhub
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
auto_tag_suffix: amd64
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.amd64
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: thegeeklab/${DRONE_REPO_NAME}
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
when:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
depends_on:
|
||||||
|
- dryrun
|
||||||
|
|
||||||
|
- name: publish-quay
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
auto_tag_suffix: amd64
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.amd64
|
||||||
|
password:
|
||||||
|
from_secret: quay_password
|
||||||
|
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
|
||||||
|
|
||||||
|
image_pull_secrets:
|
||||||
|
- docker_config
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
- refs/pull/**
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- test
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: build-container-arm64
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: golang:1.15
|
||||||
|
commands:
|
||||||
|
- "[ -z \"${DRONE_TAG}\" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}"
|
||||||
|
- go build -v -ldflags "-X main.version=$BUILD_VERSION" -a -tags netgo -o release/arm64/drone-docker ./cmd/drone-docker
|
||||||
|
|
||||||
|
- name: dryrun
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.arm64
|
||||||
|
dry_run: true
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: thegeeklab/${DRONE_REPO_NAME}
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
when:
|
||||||
|
ref:
|
||||||
|
- refs/pull/**
|
||||||
|
depends_on:
|
||||||
|
- build
|
||||||
|
|
||||||
|
- name: publish-dockerhub
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
auto_tag_suffix: arm64
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.arm64
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
repo: thegeeklab/${DRONE_REPO_NAME}
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
when:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
depends_on:
|
||||||
|
- dryrun
|
||||||
|
|
||||||
|
- name: publish-quay
|
||||||
|
image: plugins/docker:19
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
auto_tag_suffix: arm64
|
||||||
|
config:
|
||||||
|
from_secret: docker_config
|
||||||
|
dockerfile: docker/Dockerfile.arm64
|
||||||
|
password:
|
||||||
|
from_secret: quay_password
|
||||||
|
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
|
||||||
|
|
||||||
|
image_pull_secrets:
|
||||||
|
- docker_config
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
- refs/pull/**
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- test
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: notifications
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: amd64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: manifest-dockerhub
|
||||||
|
image: plugins/manifest
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
ignore_missing: true
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
|
spec: docker/manifest.tmpl
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
|
||||||
|
- name: manifest-quay
|
||||||
|
image: plugins/manifest
|
||||||
|
settings:
|
||||||
|
auto_tag: true
|
||||||
|
ignore_missing: true
|
||||||
|
password:
|
||||||
|
from_secret: quay_password
|
||||||
|
spec: docker/manifest-quay.tmpl
|
||||||
|
username:
|
||||||
|
from_secret: quay_username
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
|
||||||
|
- 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 build multiarch Docker images
|
||||||
|
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: plugins/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 }}) ({{ build.branch }}) by {{ build.author }}<br/> Message: {{ build.message }}"
|
||||||
|
username:
|
||||||
|
from_secret: matrix_username
|
||||||
|
when:
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
- failure
|
||||||
|
|
||||||
|
image_pull_secrets:
|
||||||
|
- docker_config
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
ref:
|
||||||
|
- refs/heads/main
|
||||||
|
- refs/tags/**
|
||||||
|
status:
|
||||||
|
- success
|
||||||
|
- failure
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- build-binaries
|
||||||
|
- build-container-amd64
|
||||||
|
- build-container-arm64
|
||||||
|
|
||||||
|
...
|
55
.github/settings.yml
vendored
Normal file
55
.github/settings.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
repository:
|
||||||
|
name: drone-docker
|
||||||
|
description: Drone plugin to build multiarch Docker images
|
||||||
|
topics: drone, drone-plugin
|
||||||
|
|
||||||
|
private: false
|
||||||
|
has_issues: true
|
||||||
|
has_wiki: false
|
||||||
|
has_downloads: true
|
||||||
|
|
||||||
|
default_branch: master
|
||||||
|
|
||||||
|
allow_squash_merge: true
|
||||||
|
allow_merge_commit: true
|
||||||
|
allow_rebase_merge: true
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- name: bug
|
||||||
|
color: d73a4a
|
||||||
|
description: Something isn't working
|
||||||
|
- name: documentation
|
||||||
|
color: 0075ca
|
||||||
|
description: Improvements or additions to documentation
|
||||||
|
- name: duplicate
|
||||||
|
color: cfd3d7
|
||||||
|
description: This issue or pull request already exists
|
||||||
|
- name: enhancement
|
||||||
|
color: a2eeef
|
||||||
|
description: New feature or request
|
||||||
|
- name: good first issue
|
||||||
|
color: 7057ff
|
||||||
|
description: Good for newcomers
|
||||||
|
- name: help wanted
|
||||||
|
color: 008672
|
||||||
|
description: Extra attention is needed
|
||||||
|
- name: invalid
|
||||||
|
color: e4e669
|
||||||
|
description: This doesn't seem right
|
||||||
|
- name: question
|
||||||
|
color: d876e3
|
||||||
|
description: Further information is requested
|
||||||
|
- name: wontfix
|
||||||
|
color: ffffff
|
||||||
|
description: This will not be worked on
|
||||||
|
|
||||||
|
branches:
|
||||||
|
- name: master
|
||||||
|
protection:
|
||||||
|
required_pull_request_reviews: null
|
||||||
|
required_status_checks:
|
||||||
|
strict: true
|
||||||
|
contexts:
|
||||||
|
- continuous-integration/drone/pr
|
||||||
|
enforce_admins: null
|
||||||
|
restrictions: null
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/release/
|
||||||
|
/drone-docker*
|
||||||
|
|
||||||
|
coverage.out
|
202
LICENSE
Normal file
202
LICENSE
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2021 Robert Kaussow <mail@thegeeklab.de>
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
56
README.md
Normal file
56
README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# drone-docker
|
||||||
|
|
||||||
|
Drone plugin to build multiarch Docker images
|
||||||
|
|
||||||
|
[![Build Status](https://img.shields.io/drone/build/thegeeklab/drone-docker?logo=drone)](https://cloud.drone.io/thegeeklab/drone-docker)
|
||||||
|
[![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/drone-docker)
|
||||||
|
[![Quay.io](https://img.shields.io/badge/quay-latest-blue.svg?logo=docker&logoColor=white)](https://quay.io/repository/thegeeklab/drone-docker)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/thegeeklab/drone-docker)](https://goreportcard.com/report/github.com/thegeeklab/drone-docker)
|
||||||
|
[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/drone-docker)](https://github.com/thegeeklab/drone-docker/graphs/contributors)
|
||||||
|
[![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/drone-docker)
|
||||||
|
[![License: MIT](https://img.shields.io/github/license/thegeeklab/drone-docker)](https://github.com/thegeeklab/drone-docker/blob/main/LICENSE)
|
||||||
|
|
||||||
|
Drone plugin to build multiarch Docker images.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
Build the binary with the following command:
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
export GOOS=linux
|
||||||
|
export GOARCH=amd64
|
||||||
|
export CGO_ENABLED=0
|
||||||
|
export GO111MODULE=on
|
||||||
|
|
||||||
|
go build -v -a -tags netgo -o release/drone-docker
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the Docker image with the following command:
|
||||||
|
|
||||||
|
```Shell
|
||||||
|
docker build --file docker/Dockerfile.amd64 --tag thegeeklab/drone-docker .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
> Notice: Be aware that the tis plugin requires privileged capabilities, otherwise the integrated Docker daemon is not able to start.
|
||||||
|
|
||||||
|
```console
|
||||||
|
docker run --rm \
|
||||||
|
-e PLUGIN_TAG=latest \
|
||||||
|
-e PLUGIN_REPO=octocat/hello-world \
|
||||||
|
-e DRONE_COMMIT_SHA=00000000 \
|
||||||
|
-v $(pwd):$(pwd) \
|
||||||
|
-w $(pwd) \
|
||||||
|
--privileged \
|
||||||
|
thegeeklab/drone-docker --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
Special thanks goes to all [contributors](https://github.com/thegeeklab/drone-docker/graphs/contributors). If you would like to contribute,
|
||||||
|
please see the [instructions](https://github.com/thegeeklab/drone-docker/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](https://github.com/thegeeklab/drone-docker/blob/main/LICENSE) file for details.
|
236
cmd/drone-docker/config.go
Normal file
236
cmd/drone-docker/config.go
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/thegeeklab/drone-docker/plugin"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// settingsFlags has the cli.Flags for the plugin.Settings.
|
||||||
|
func settingsFlags(settings *plugin.Settings) []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "dry-run",
|
||||||
|
Usage: "dry run disables docker push",
|
||||||
|
EnvVars: []string{"PLUGIN_DRY_RUN"},
|
||||||
|
Destination: &settings.Dryrun,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "remote.url",
|
||||||
|
Usage: "git remote url",
|
||||||
|
EnvVars: []string{"DRONE_REMOTE_URL"},
|
||||||
|
Destination: &settings.Build.Remote,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "daemon.mirror",
|
||||||
|
Usage: "docker daemon registry mirror",
|
||||||
|
EnvVars: []string{"PLUGIN_MIRROR", "DOCKER_PLUGIN_MIRROR"},
|
||||||
|
Destination: &settings.Daemon.Mirror,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "daemon.storage-driver",
|
||||||
|
Usage: "docker daemon storage driver",
|
||||||
|
EnvVars: []string{"PLUGIN_STORAGE_DRIVER"},
|
||||||
|
Destination: &settings.Daemon.StorageDriver,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "daemon.storage-path",
|
||||||
|
Usage: "docker daemon storage path",
|
||||||
|
Value: "/var/lib/docker",
|
||||||
|
EnvVars: []string{"PLUGIN_STORAGE_PATH"},
|
||||||
|
Destination: &settings.Daemon.StoragePath,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "daemon.bip",
|
||||||
|
Usage: "docker daemon bride ip address",
|
||||||
|
EnvVars: []string{"PLUGIN_BIP"},
|
||||||
|
Destination: &settings.Daemon.Bip,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "daemon.mtu",
|
||||||
|
Usage: "docker daemon custom mtu setting",
|
||||||
|
EnvVars: []string{"PLUGIN_MTU"},
|
||||||
|
Destination: &settings.Daemon.MTU,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "daemon.dns",
|
||||||
|
Usage: "docker daemon dns server",
|
||||||
|
EnvVars: []string{"PLUGIN_CUSTOM_DNS"},
|
||||||
|
Destination: &settings.Daemon.DNS,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "daemon.dns-search",
|
||||||
|
Usage: "docker daemon dns search domains",
|
||||||
|
EnvVars: []string{"PLUGIN_CUSTOM_DNS_SEARCH"},
|
||||||
|
Destination: &settings.Daemon.DNSSearch,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "daemon.insecure",
|
||||||
|
Usage: "docker daemon allows insecure registries",
|
||||||
|
EnvVars: []string{"PLUGIN_INSECURE"},
|
||||||
|
Destination: &settings.Daemon.Insecure,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "daemon.ipv6",
|
||||||
|
Usage: "docker daemon IPv6 networking",
|
||||||
|
EnvVars: []string{"PLUGIN_IPV6"},
|
||||||
|
Destination: &settings.Daemon.IPv6,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "daemon.experimental",
|
||||||
|
Usage: "docker daemon Experimental mode",
|
||||||
|
EnvVars: []string{"PLUGIN_EXPERIMENTAL"},
|
||||||
|
Destination: &settings.Daemon.Experimental,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "daemon.debug",
|
||||||
|
Usage: "docker daemon executes in debug mode",
|
||||||
|
EnvVars: []string{"PLUGIN_DEBUG", "DOCKER_LAUNCH_DEBUG"},
|
||||||
|
Destination: &settings.Daemon.Debug,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "daemon.off",
|
||||||
|
Usage: "don't start the docker daemon",
|
||||||
|
EnvVars: []string{"PLUGIN_DAEMON_OFF"},
|
||||||
|
Destination: &settings.Daemon.Disabled,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "dockerfile",
|
||||||
|
Usage: "build dockerfile",
|
||||||
|
Value: "Dockerfile",
|
||||||
|
EnvVars: []string{"PLUGIN_DOCKERFILE"},
|
||||||
|
Destination: &settings.Build.Dockerfile,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "context",
|
||||||
|
Usage: "build context",
|
||||||
|
Value: ".",
|
||||||
|
EnvVars: []string{"PLUGIN_CONTEXT"},
|
||||||
|
Destination: &settings.Build.Context,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "tags",
|
||||||
|
Usage: "build tags",
|
||||||
|
Value: cli.NewStringSlice([]string{"latest"}...),
|
||||||
|
EnvVars: []string{"PLUGIN_TAG", "PLUGIN_TAGS"},
|
||||||
|
FilePath: ".tags",
|
||||||
|
Destination: &settings.Build.Tags,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "tags.auto",
|
||||||
|
Usage: "default build tags",
|
||||||
|
EnvVars: []string{"PLUGIN_DEFAULT_TAGS", "PLUGIN_AUTO_TAG"},
|
||||||
|
Destination: &settings.Build.TagsAuto,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "tags.suffix",
|
||||||
|
Usage: "default build tags with suffix",
|
||||||
|
EnvVars: []string{"PLUGIN_DEFAULT_SUFFIX", "PLUGIN_AUTO_TAG_SUFFIX"},
|
||||||
|
Destination: &settings.Build.TagsSuffix,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "args",
|
||||||
|
Usage: "build args",
|
||||||
|
EnvVars: []string{"PLUGIN_BUILD_ARGS"},
|
||||||
|
Destination: &settings.Build.Args,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "args-from-env",
|
||||||
|
Usage: "build args",
|
||||||
|
EnvVars: []string{"PLUGIN_BUILD_ARGS_FROM_ENV"},
|
||||||
|
Destination: &settings.Build.ArgsEnv,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "quiet",
|
||||||
|
Usage: "quiet docker build",
|
||||||
|
EnvVars: []string{"PLUGIN_QUIET"},
|
||||||
|
Destination: &settings.Build.Quiet,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "target",
|
||||||
|
Usage: "build target",
|
||||||
|
EnvVars: []string{"PLUGIN_TARGET"},
|
||||||
|
Destination: &settings.Build.Target,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "cache-from",
|
||||||
|
Usage: "images to consider as cache sources",
|
||||||
|
EnvVars: []string{"PLUGIN_CACHE_FROM"},
|
||||||
|
Destination: &settings.Build.CacheFrom,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "squash",
|
||||||
|
Usage: "squash the layers at build time",
|
||||||
|
EnvVars: []string{"PLUGIN_SQUASH"},
|
||||||
|
Destination: &settings.Build.Squash,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "pull-image",
|
||||||
|
Usage: "force pull base image at build time",
|
||||||
|
EnvVars: []string{"PLUGIN_PULL_IMAGE"},
|
||||||
|
Value: true,
|
||||||
|
Destination: &settings.Build.Pull,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "compress",
|
||||||
|
Usage: "compress the build context using gzip",
|
||||||
|
EnvVars: []string{"PLUGIN_COMPRESS"},
|
||||||
|
Destination: &settings.Build.Compress,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "repo",
|
||||||
|
Usage: "docker repository",
|
||||||
|
EnvVars: []string{"PLUGIN_REPO"},
|
||||||
|
Destination: &settings.Build.Repo,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "docker.registry",
|
||||||
|
Usage: "docker registry",
|
||||||
|
Value: "https://index.docker.io/v1/",
|
||||||
|
EnvVars: []string{"PLUGIN_REGISTRY", "DOCKER_REGISTRY"},
|
||||||
|
Destination: &settings.Login.Registry,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "docker.username",
|
||||||
|
Usage: "docker username",
|
||||||
|
EnvVars: []string{"PLUGIN_USERNAME", "DOCKER_USERNAME"},
|
||||||
|
Destination: &settings.Login.Username,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "docker.password",
|
||||||
|
Usage: "docker password",
|
||||||
|
EnvVars: []string{"PLUGIN_PASSWORD", "DOCKER_PASSWORD"},
|
||||||
|
Destination: &settings.Login.Password,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "docker.email",
|
||||||
|
Usage: "docker email",
|
||||||
|
EnvVars: []string{"PLUGIN_EMAIL", "DOCKER_EMAIL"},
|
||||||
|
Destination: &settings.Login.Email,
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "docker.config",
|
||||||
|
Usage: "docker json dockerconfig content",
|
||||||
|
EnvVars: []string{"PLUGIN_CONFIG", "DOCKER_PLUGIN_CONFIG"},
|
||||||
|
Destination: &settings.Login.Config,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "docker.purge",
|
||||||
|
Usage: "docker should cleanup images",
|
||||||
|
EnvVars: []string{"PLUGIN_PURGE"},
|
||||||
|
Value: true,
|
||||||
|
Destination: &settings.Cleanup,
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "no-cache",
|
||||||
|
Usage: "do not use cached intermediate containers",
|
||||||
|
EnvVars: []string{"PLUGIN_NO_CACHE"},
|
||||||
|
Destination: &settings.Build.NoCache,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "add-host",
|
||||||
|
Usage: "additional host:IP mapping",
|
||||||
|
EnvVars: []string{"PLUGIN_ADD_HOST"},
|
||||||
|
Destination: &settings.Build.AddHost,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
64
cmd/drone-docker/main.go
Normal file
64
cmd/drone-docker/main.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/thegeeklab/drone-docker/plugin"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
"github.com/drone-plugins/drone-plugin-lib/errors"
|
||||||
|
"github.com/drone-plugins/drone-plugin-lib/urfave"
|
||||||
|
)
|
||||||
|
|
||||||
|
var version = "unknown"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
settings := &plugin.Settings{}
|
||||||
|
|
||||||
|
if _, err := os.Stat("/run/drone/env"); err == nil {
|
||||||
|
godotenv.Overload("/run/drone/env")
|
||||||
|
}
|
||||||
|
|
||||||
|
app := &cli.App{
|
||||||
|
Name: "drone-docker",
|
||||||
|
Usage: "build docker container with DinD",
|
||||||
|
Version: version,
|
||||||
|
Flags: append(settingsFlags(settings), urfave.Flags()...),
|
||||||
|
Action: run(settings),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
errors.HandleExit(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(settings *plugin.Settings) cli.ActionFunc {
|
||||||
|
return func(ctx *cli.Context) error {
|
||||||
|
urfave.LoggingFromContext(ctx)
|
||||||
|
|
||||||
|
plugin := plugin.New(
|
||||||
|
*settings,
|
||||||
|
urfave.PipelineFromContext(ctx),
|
||||||
|
urfave.NetworkFromContext(ctx),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := plugin.Validate(); err != nil {
|
||||||
|
if e, ok := err.(errors.ExitCoder); ok {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.ExitMessagef("validation failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := plugin.Execute(); err != nil {
|
||||||
|
if e, ok := err.(errors.ExitCoder); ok {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.ExitMessagef("execution failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
23
docker/Dockerfile.amd64
Normal file
23
docker/Dockerfile.amd64
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FROM amd64/docker:19.03-dind
|
||||||
|
|
||||||
|
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.title="drone-docker"
|
||||||
|
LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-docker"
|
||||||
|
|
||||||
|
ENV DOCKER_HOST=unix:///var/run/docker.sock
|
||||||
|
|
||||||
|
RUN apk --update add --virtual .build-deps curl && \
|
||||||
|
mkdir -p /etc/docker/ && \
|
||||||
|
curl -SsL -o /etc/docker/default.json https://github.com/moby/moby/blob/19.03/profiles/seccomp/default.json && \
|
||||||
|
sed -i 's/SCMP_ACT_ERRNO/SCMP_ACT_TRACE/g' /etc/docker/default.json && \
|
||||||
|
chmod 600 /etc/docker/default.json && \
|
||||||
|
apk del .build-deps && \
|
||||||
|
rm -rf /var/cache/apk/* && \
|
||||||
|
rm -rf /tmp/*
|
||||||
|
|
||||||
|
ADD release/amd64/drone-docker /bin/
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "drone-docker"]
|
23
docker/Dockerfile.arm
Normal file
23
docker/Dockerfile.arm
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FROM arm32v7/docker:19.03-dind
|
||||||
|
|
||||||
|
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.title="drone-docker"
|
||||||
|
LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-docker"
|
||||||
|
|
||||||
|
ENV DOCKER_HOST=unix:///var/run/docker.sock
|
||||||
|
|
||||||
|
RUN apk --update add --virtual .build-deps curl && \
|
||||||
|
mkdir -p /etc/docker/ && \
|
||||||
|
curl -SsL -o /etc/docker/default.json https://github.com/moby/moby/blob/19.03/profiles/seccomp/default.json && \
|
||||||
|
sed -i 's/SCMP_ACT_ERRNO/SCMP_ACT_TRACE/g' /etc/docker/default.json && \
|
||||||
|
chmod 600 /etc/docker/default.json && \
|
||||||
|
apk del .build-deps && \
|
||||||
|
rm -rf /var/cache/apk/* && \
|
||||||
|
rm -rf /tmp/*
|
||||||
|
|
||||||
|
ADD release/arm/drone-docker /bin/
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "drone-docker"]
|
23
docker/Dockerfile.arm64
Normal file
23
docker/Dockerfile.arm64
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
FROM arm64v8/docker:19.03-dind
|
||||||
|
|
||||||
|
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
|
||||||
|
LABEL org.opencontainers.image.title="drone-docker"
|
||||||
|
LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-docker"
|
||||||
|
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-docker"
|
||||||
|
|
||||||
|
ENV DOCKER_HOST=unix:///var/run/docker.sock
|
||||||
|
|
||||||
|
RUN apk --update add --virtual .build-deps curl && \
|
||||||
|
mkdir -p /etc/docker/ && \
|
||||||
|
curl -SsL -o /etc/docker/default.json https://github.com/moby/moby/blob/19.03/profiles/seccomp/default.json && \
|
||||||
|
sed -i 's/SCMP_ACT_ERRNO/SCMP_ACT_TRACE/g' /etc/docker/default.json && \
|
||||||
|
chmod 600 /etc/docker/default.json && \
|
||||||
|
apk del .build-deps && \
|
||||||
|
rm -rf /var/cache/apk/* && \
|
||||||
|
rm -rf /tmp/*
|
||||||
|
|
||||||
|
ADD release/arm64/drone-docker /bin/
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/dockerd-entrypoint.sh", "drone-docker"]
|
24
docker/manifest-quay.tmpl
Normal file
24
docker/manifest-quay.tmpl
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
image: quay.io/thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||||
|
{{#if build.tags}}
|
||||||
|
tags:
|
||||||
|
{{#each build.tags}}
|
||||||
|
- {{this}}
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
manifests:
|
||||||
|
- image: quay.io/thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}amd64
|
||||||
|
platform:
|
||||||
|
architecture: amd64
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
- image: quay.io/thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm64
|
||||||
|
platform:
|
||||||
|
architecture: arm64
|
||||||
|
os: linux
|
||||||
|
variant: v8
|
||||||
|
|
||||||
|
- image: quay.io/thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm
|
||||||
|
platform:
|
||||||
|
architecture: arm
|
||||||
|
os: linux
|
||||||
|
variant: v7
|
24
docker/manifest.tmpl
Normal file
24
docker/manifest.tmpl
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
image: thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
||||||
|
{{#if build.tags}}
|
||||||
|
tags:
|
||||||
|
{{#each build.tags}}
|
||||||
|
- {{this}}
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
manifests:
|
||||||
|
- image: thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}amd64
|
||||||
|
platform:
|
||||||
|
architecture: amd64
|
||||||
|
os: linux
|
||||||
|
|
||||||
|
- image: thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm64
|
||||||
|
platform:
|
||||||
|
architecture: arm64
|
||||||
|
os: linux
|
||||||
|
variant: v8
|
||||||
|
|
||||||
|
- image: thegeeklab/drone-docker:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm
|
||||||
|
platform:
|
||||||
|
architecture: arm
|
||||||
|
os: linux
|
||||||
|
variant: v7
|
16
go.mod
Normal file
16
go.mod
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module github.com/thegeeklab/drone-docker
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/coreos/go-semver v0.3.0
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||||
|
github.com/drone-plugins/drone-plugin-lib v0.4.0
|
||||||
|
github.com/joho/godotenv v1.3.0
|
||||||
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.7.0
|
||||||
|
github.com/urfave/cli/v2 v2.3.0
|
||||||
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 // indirect
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.13
|
58
go.sum
Normal file
58
go.sum
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||||
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
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/drone-plugins/drone-plugin-lib v0.4.0 h1:qywEYGhquUuid6zNLmKia8CWY1TUa8jPQQ/G9ozfAmc=
|
||||||
|
github.com/drone-plugins/drone-plugin-lib v0.4.0/go.mod h1:EgqogX38GoJFtckeSQyhBJYX8P+KWBPhdprAVvyRxF8=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/pkg/errors v0.8.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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
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/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||||
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
|
||||||
|
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||||
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
|
||||||
|
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
25
plugin/daemon.go
Normal file
25
plugin/daemon.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dockerExe = "/usr/local/bin/docker"
|
||||||
|
const dockerdExe = "/usr/local/bin/dockerd"
|
||||||
|
const dockerHome = "/root/.docker/"
|
||||||
|
|
||||||
|
func (p Plugin) startDaemon() {
|
||||||
|
cmd := commandDaemon(p.settings.Daemon)
|
||||||
|
if p.settings.Daemon.Debug {
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
} else {
|
||||||
|
cmd.Stdout = ioutil.Discard
|
||||||
|
cmd.Stderr = ioutil.Discard
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
trace(cmd)
|
||||||
|
cmd.Run()
|
||||||
|
}()
|
||||||
|
}
|
217
plugin/docker.go
Normal file
217
plugin/docker.go
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// helper function to create the docker login command.
|
||||||
|
func commandLogin(login Login) *exec.Cmd {
|
||||||
|
if login.Email != "" {
|
||||||
|
return commandLoginEmail(login)
|
||||||
|
}
|
||||||
|
return exec.Command(
|
||||||
|
dockerExe, "login",
|
||||||
|
"-u", login.Username,
|
||||||
|
"-p", login.Password,
|
||||||
|
login.Registry,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper to check if args match "docker pull <image>"
|
||||||
|
func isCommandPull(args []string) bool {
|
||||||
|
return len(args) > 2 && args[1] == "pull"
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandPull(repo string) *exec.Cmd {
|
||||||
|
return exec.Command(dockerExe, "pull", repo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandLoginEmail(login Login) *exec.Cmd {
|
||||||
|
return exec.Command(
|
||||||
|
dockerExe, "login",
|
||||||
|
"-u", login.Username,
|
||||||
|
"-p", login.Password,
|
||||||
|
"-e", login.Email,
|
||||||
|
login.Registry,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker info command.
|
||||||
|
func commandVersion() *exec.Cmd {
|
||||||
|
return exec.Command(dockerExe, "version")
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker info command.
|
||||||
|
func commandInfo() *exec.Cmd {
|
||||||
|
return exec.Command(dockerExe, "info")
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker build command.
|
||||||
|
func commandBuild(build Build) *exec.Cmd {
|
||||||
|
args := []string{
|
||||||
|
"build",
|
||||||
|
"--rm=true",
|
||||||
|
"-f", build.Dockerfile,
|
||||||
|
"-t", build.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, build.Context)
|
||||||
|
if build.Squash {
|
||||||
|
args = append(args, "--squash")
|
||||||
|
}
|
||||||
|
if build.Compress {
|
||||||
|
args = append(args, "--compress")
|
||||||
|
}
|
||||||
|
if build.Pull {
|
||||||
|
args = append(args, "--pull=true")
|
||||||
|
}
|
||||||
|
if build.NoCache {
|
||||||
|
args = append(args, "--no-cache")
|
||||||
|
}
|
||||||
|
for _, arg := range build.CacheFrom.Value() {
|
||||||
|
args = append(args, "--cache-from", arg)
|
||||||
|
}
|
||||||
|
for _, arg := range build.ArgsEnv.Value() {
|
||||||
|
addProxyValue(&build, arg)
|
||||||
|
}
|
||||||
|
for _, arg := range build.Args.Value() {
|
||||||
|
args = append(args, "--build-arg", arg)
|
||||||
|
}
|
||||||
|
for _, host := range build.AddHost.Value() {
|
||||||
|
args = append(args, "--add-host", host)
|
||||||
|
}
|
||||||
|
if build.Target != "" {
|
||||||
|
args = append(args, "--target", build.Target)
|
||||||
|
}
|
||||||
|
if build.Quiet {
|
||||||
|
args = append(args, "--quiet")
|
||||||
|
}
|
||||||
|
|
||||||
|
return exec.Command(dockerExe, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to add proxy values from the environment
|
||||||
|
func addProxyBuildArgs(build *Build) {
|
||||||
|
addProxyValue(build, "http_proxy")
|
||||||
|
addProxyValue(build, "https_proxy")
|
||||||
|
addProxyValue(build, "no_proxy")
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to add the upper and lower case version of a proxy value.
|
||||||
|
func addProxyValue(build *Build, key string) {
|
||||||
|
value := getProxyValue(key)
|
||||||
|
|
||||||
|
if len(value) > 0 && !hasProxyBuildArg(build, key) {
|
||||||
|
build.Args = *cli.NewStringSlice(append(build.Args.Value(), fmt.Sprintf("%s=%s", key, value))...)
|
||||||
|
build.Args = *cli.NewStringSlice(append(build.Args.Value(), fmt.Sprintf("%s=%s", strings.ToUpper(key), value))...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to get a proxy value from the environment.
|
||||||
|
//
|
||||||
|
// assumes that the upper and lower case versions of are the same.
|
||||||
|
func getProxyValue(key string) string {
|
||||||
|
value := os.Getenv(key)
|
||||||
|
|
||||||
|
if len(value) > 0 {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.Getenv(strings.ToUpper(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function that looks to see if a proxy value was set in the build args.
|
||||||
|
func hasProxyBuildArg(build *Build, key string) bool {
|
||||||
|
keyUpper := strings.ToUpper(key)
|
||||||
|
|
||||||
|
for _, s := range build.Args.Value() {
|
||||||
|
if strings.HasPrefix(s, key) || strings.HasPrefix(s, keyUpper) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker tag command.
|
||||||
|
func commandTag(build Build, tag string) *exec.Cmd {
|
||||||
|
var (
|
||||||
|
source = build.Name
|
||||||
|
target = fmt.Sprintf("%s:%s", build.Repo, tag)
|
||||||
|
)
|
||||||
|
return exec.Command(
|
||||||
|
dockerExe, "tag", source, target,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker push command.
|
||||||
|
func commandPush(build Build, tag string) *exec.Cmd {
|
||||||
|
target := fmt.Sprintf("%s:%s", build.Repo, tag)
|
||||||
|
return exec.Command(dockerExe, "push", target)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to create the docker daemon command.
|
||||||
|
func commandDaemon(daemon Daemon) *exec.Cmd {
|
||||||
|
args := []string{
|
||||||
|
"--data-root", daemon.StoragePath,
|
||||||
|
"--host=unix:///var/run/docker.sock",
|
||||||
|
}
|
||||||
|
|
||||||
|
if daemon.StorageDriver != "" {
|
||||||
|
args = append(args, "-s", daemon.StorageDriver)
|
||||||
|
}
|
||||||
|
if daemon.Insecure && daemon.Registry != "" {
|
||||||
|
args = append(args, "--insecure-registry", daemon.Registry)
|
||||||
|
}
|
||||||
|
if daemon.IPv6 {
|
||||||
|
args = append(args, "--ipv6")
|
||||||
|
}
|
||||||
|
if len(daemon.Mirror) != 0 {
|
||||||
|
args = append(args, "--registry-mirror", daemon.Mirror)
|
||||||
|
}
|
||||||
|
if len(daemon.Bip) != 0 {
|
||||||
|
args = append(args, "--bip", daemon.Bip)
|
||||||
|
}
|
||||||
|
for _, dns := range daemon.DNS.Value() {
|
||||||
|
args = append(args, "--dns", dns)
|
||||||
|
}
|
||||||
|
for _, dnsSearch := range daemon.DNSSearch.Value() {
|
||||||
|
args = append(args, "--dns-search", dnsSearch)
|
||||||
|
}
|
||||||
|
if len(daemon.MTU) != 0 {
|
||||||
|
args = append(args, "--mtu", daemon.MTU)
|
||||||
|
}
|
||||||
|
if daemon.Experimental {
|
||||||
|
args = append(args, "--experimental")
|
||||||
|
}
|
||||||
|
return exec.Command(dockerdExe, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper to check if args match "docker prune"
|
||||||
|
func isCommandPrune(args []string) bool {
|
||||||
|
return len(args) > 3 && args[2] == "prune"
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandPrune() *exec.Cmd {
|
||||||
|
return exec.Command(dockerExe, "system", "prune", "-f")
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper to check if args match "docker rmi"
|
||||||
|
func isCommandRmi(args []string) bool {
|
||||||
|
return len(args) > 2 && args[1] == "rmi"
|
||||||
|
}
|
||||||
|
|
||||||
|
func commandRmi(tag string) *exec.Cmd {
|
||||||
|
return exec.Command(dockerExe, "rmi", tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// trace writes each command to stdout with the command wrapped in an xml
|
||||||
|
// tag so that it can be extracted and displayed in the logs.
|
||||||
|
func trace(cmd *exec.Cmd) {
|
||||||
|
fmt.Fprintf(os.Stdout, "+ %s\n", strings.Join(cmd.Args, " "))
|
||||||
|
}
|
1
plugin/docker_test.go
Normal file
1
plugin/docker_test.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package plugin
|
207
plugin/impl.go
Normal file
207
plugin/impl.go
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Daemon defines Docker daemon parameters.
|
||||||
|
type Daemon struct {
|
||||||
|
Registry string // Docker registry
|
||||||
|
Mirror string // Docker registry mirror
|
||||||
|
Insecure bool // Docker daemon enable insecure registries
|
||||||
|
StorageDriver string // Docker daemon storage driver
|
||||||
|
StoragePath string // Docker daemon storage path
|
||||||
|
Disabled bool // DOcker daemon is disabled (already running)
|
||||||
|
Debug bool // Docker daemon started in debug mode
|
||||||
|
Bip string // Docker daemon network bridge IP address
|
||||||
|
DNS cli.StringSlice // Docker daemon dns server
|
||||||
|
DNSSearch cli.StringSlice // Docker daemon dns search domain
|
||||||
|
MTU string // Docker daemon mtu setting
|
||||||
|
IPv6 bool // Docker daemon IPv6 networking
|
||||||
|
Experimental bool // Docker daemon enable experimental mode
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login defines Docker login parameters.
|
||||||
|
type Login struct {
|
||||||
|
Registry string // Docker registry address
|
||||||
|
Username string // Docker registry username
|
||||||
|
Password string // Docker registry password
|
||||||
|
Email string // Docker registry email
|
||||||
|
Config string // Docker Auth Config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build defines Docker build parameters.
|
||||||
|
type Build struct {
|
||||||
|
Remote string // Git remote URL
|
||||||
|
Name string // Git commit sha used as docker default named tag
|
||||||
|
Ref string // Git commit ref
|
||||||
|
Branch string // Git repository branch
|
||||||
|
Dockerfile string // Docker build Dockerfile
|
||||||
|
Context string // Docker build context
|
||||||
|
TagsAuto bool // Docker build auto tag
|
||||||
|
TagsSuffix string // Docker build tags with suffix
|
||||||
|
Tags cli.StringSlice // Docker build tags
|
||||||
|
Args cli.StringSlice // Docker build args
|
||||||
|
ArgsEnv cli.StringSlice // Docker build args from env
|
||||||
|
Target string // Docker build target
|
||||||
|
Squash bool // Docker build squash
|
||||||
|
Pull bool // Docker build pull
|
||||||
|
CacheFrom cli.StringSlice // Docker build cache-from
|
||||||
|
Compress bool // Docker build compress
|
||||||
|
Repo string // Docker build repository
|
||||||
|
NoCache bool // Docker build no-cache
|
||||||
|
AddHost cli.StringSlice // Docker build add-host
|
||||||
|
Quiet bool // Docker build quiet
|
||||||
|
}
|
||||||
|
|
||||||
|
// Settings for the Plugin.
|
||||||
|
type Settings struct {
|
||||||
|
Daemon Daemon
|
||||||
|
Login Login
|
||||||
|
Build Build
|
||||||
|
Dryrun bool
|
||||||
|
Cleanup bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate handles the settings validation of the plugin.
|
||||||
|
func (p *Plugin) Validate() error {
|
||||||
|
p.settings.Build.Name = "00000000"
|
||||||
|
if p.pipeline.Commit.SHA != "" {
|
||||||
|
p.settings.Build.Name = p.pipeline.Commit.SHA
|
||||||
|
}
|
||||||
|
|
||||||
|
p.settings.Build.Branch = p.pipeline.Repo.Branch
|
||||||
|
p.settings.Build.Ref = p.pipeline.Commit.Ref
|
||||||
|
p.settings.Daemon.Registry = p.settings.Login.Registry
|
||||||
|
|
||||||
|
if p.settings.Build.TagsAuto {
|
||||||
|
// return true if tag event or default branch
|
||||||
|
if UseDefaultTag(
|
||||||
|
p.settings.Build.Ref,
|
||||||
|
p.settings.Build.Branch,
|
||||||
|
) {
|
||||||
|
tag, err := DefaultTagSuffix(
|
||||||
|
p.settings.Build.Ref,
|
||||||
|
p.settings.Build.TagsSuffix,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Printf("cannot build docker image for %s, invalid semantic version", p.settings.Build.Ref)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
p.settings.Build.Tags = *cli.NewStringSlice(tag...)
|
||||||
|
} else {
|
||||||
|
logrus.Printf("skipping automated docker build for %s", p.settings.Build.Ref)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute provides the implementation of the plugin.
|
||||||
|
func (p *Plugin) Execute() error {
|
||||||
|
// start the Docker daemon server
|
||||||
|
if !p.settings.Daemon.Disabled {
|
||||||
|
p.startDaemon()
|
||||||
|
}
|
||||||
|
|
||||||
|
// poll the docker daemon until it is started. This ensures the daemon is
|
||||||
|
// ready to accept connections before we proceed.
|
||||||
|
for i := 0; i < 15; i++ {
|
||||||
|
cmd := commandInfo()
|
||||||
|
err := cmd.Run()
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Auth Config File
|
||||||
|
if p.settings.Login.Config != "" {
|
||||||
|
os.MkdirAll(dockerHome, 0600)
|
||||||
|
|
||||||
|
path := filepath.Join(dockerHome, "config.json")
|
||||||
|
err := ioutil.WriteFile(path, []byte(p.settings.Login.Config), 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error writing config.json: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// login to the Docker registry
|
||||||
|
if p.settings.Login.Password != "" {
|
||||||
|
cmd := commandLogin(p.settings.Login)
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error authenticating: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case p.settings.Login.Password != "":
|
||||||
|
fmt.Println("Detected registry credentials")
|
||||||
|
case p.settings.Login.Config != "":
|
||||||
|
fmt.Println("Detected registry credentials file")
|
||||||
|
default:
|
||||||
|
fmt.Println("Registry credentials or Docker config not provided. Guest mode enabled.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.settings.Build.Squash && !p.settings.Daemon.Experimental {
|
||||||
|
fmt.Println("Squash build flag is only available when Docker deamon is started with experimental flag. Ignoring...")
|
||||||
|
p.settings.Build.Squash = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// add proxy build args
|
||||||
|
addProxyBuildArgs(&p.settings.Build)
|
||||||
|
|
||||||
|
var cmds []*exec.Cmd
|
||||||
|
cmds = append(cmds, commandVersion()) // docker version
|
||||||
|
cmds = append(cmds, commandInfo()) // docker info
|
||||||
|
|
||||||
|
// pre-pull cache images
|
||||||
|
for _, img := range p.settings.Build.CacheFrom.Value() {
|
||||||
|
cmds = append(cmds, commandPull(img))
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds = append(cmds, commandBuild(p.settings.Build)) // docker build
|
||||||
|
|
||||||
|
for _, tag := range p.settings.Build.Tags.Value() {
|
||||||
|
cmds = append(cmds, commandTag(p.settings.Build, tag)) // docker tag
|
||||||
|
|
||||||
|
if !p.settings.Dryrun {
|
||||||
|
cmds = append(cmds, commandPush(p.settings.Build, tag)) // docker push
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.settings.Cleanup {
|
||||||
|
cmds = append(cmds, commandRmi(p.settings.Build.Name)) // docker rmi
|
||||||
|
cmds = append(cmds, commandPrune()) // docker system prune -f
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute all commands in batch mode.
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
trace(cmd)
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil && isCommandPull(cmd.Args) {
|
||||||
|
fmt.Printf("Could not pull cache-from image %s. Ignoring...\n", cmd.Args[2])
|
||||||
|
} else if err != nil && isCommandPrune(cmd.Args) {
|
||||||
|
fmt.Printf("Could not prune system containers. Ignoring...\n")
|
||||||
|
} else if err != nil && isCommandRmi(cmd.Args) {
|
||||||
|
fmt.Printf("Could not remove image %s. Ignoring...\n", cmd.Args[2])
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
21
plugin/plugin.go
Normal file
21
plugin/plugin.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/drone-plugins/drone-plugin-lib/drone"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Plugin implements drone.Plugin to provide the plugin implementation.
|
||||||
|
type Plugin struct {
|
||||||
|
settings Settings
|
||||||
|
pipeline drone.Pipeline
|
||||||
|
network drone.Network
|
||||||
|
}
|
||||||
|
|
||||||
|
// New initializes a plugin from the given Settings, Pipeline, and Network.
|
||||||
|
func New(settings Settings, pipeline drone.Pipeline, network drone.Network) drone.Plugin {
|
||||||
|
return &Plugin{
|
||||||
|
settings: settings,
|
||||||
|
pipeline: pipeline,
|
||||||
|
network: network,
|
||||||
|
}
|
||||||
|
}
|
93
plugin/tags.go
Normal file
93
plugin/tags.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultTagSuffix returns a set of default suggested tags
|
||||||
|
// based on the commit ref with an attached suffix.
|
||||||
|
func DefaultTagSuffix(ref, suffix string) ([]string, error) {
|
||||||
|
tags, err := DefaultTags(ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(suffix) == 0 {
|
||||||
|
return tags, nil
|
||||||
|
}
|
||||||
|
for i, tag := range tags {
|
||||||
|
if tag == "latest" {
|
||||||
|
tags[i] = suffix
|
||||||
|
} else {
|
||||||
|
tags[i] = fmt.Sprintf("%s-%s", tag, suffix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitOff(input string, delim string) string {
|
||||||
|
parts := strings.SplitN(input, delim, 2)
|
||||||
|
|
||||||
|
if len(parts) == 2 {
|
||||||
|
return parts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultTags returns a set of default suggested tags based on
|
||||||
|
// the commit ref.
|
||||||
|
func DefaultTags(ref string) ([]string, error) {
|
||||||
|
if !strings.HasPrefix(ref, "refs/tags/") {
|
||||||
|
return []string{"latest"}, nil
|
||||||
|
}
|
||||||
|
v := stripTagPrefix(ref)
|
||||||
|
version, err := semver.NewVersion(v)
|
||||||
|
if err != nil {
|
||||||
|
return []string{"latest"}, err
|
||||||
|
}
|
||||||
|
if version.PreRelease != "" || version.Metadata != "" {
|
||||||
|
return []string{
|
||||||
|
version.String(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v = stripTagPrefix(ref)
|
||||||
|
v = splitOff(splitOff(v, "+"), "-")
|
||||||
|
dotParts := strings.SplitN(v, ".", 3)
|
||||||
|
|
||||||
|
if version.Major == 0 {
|
||||||
|
return []string{
|
||||||
|
fmt.Sprintf("%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor),
|
||||||
|
fmt.Sprintf("%0*d.%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor, len(dotParts[2]), version.Patch),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
return []string{
|
||||||
|
fmt.Sprintf("%0*d", len(dotParts[0]), version.Major),
|
||||||
|
fmt.Sprintf("%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor),
|
||||||
|
fmt.Sprintf("%0*d.%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor, len(dotParts[2]), version.Patch),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UseDefaultTag for keep only default branch for latest tag
|
||||||
|
func UseDefaultTag(ref, defaultBranch string) bool {
|
||||||
|
if strings.HasPrefix(ref, "refs/tags/") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if stripHeadPrefix(ref) == defaultBranch {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripHeadPrefix(ref string) string {
|
||||||
|
return strings.TrimPrefix(ref, "refs/heads/")
|
||||||
|
}
|
||||||
|
|
||||||
|
func stripTagPrefix(ref string) string {
|
||||||
|
ref = strings.TrimPrefix(ref, "refs/tags/")
|
||||||
|
ref = strings.TrimPrefix(ref, "v")
|
||||||
|
return ref
|
||||||
|
}
|
197
plugin/tags_test.go
Normal file
197
plugin/tags_test.go
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_stripTagPrefix(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
Before string
|
||||||
|
After string
|
||||||
|
}{
|
||||||
|
{"refs/tags/1.0.0", "1.0.0"},
|
||||||
|
{"refs/tags/v1.0.0", "1.0.0"},
|
||||||
|
{"v1.0.0", "1.0.0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
got, want := stripTagPrefix(test.Before), test.After
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("Got tag %s, want %s", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultTags(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
Before string
|
||||||
|
After []string
|
||||||
|
}{
|
||||||
|
{"", []string{"latest"}},
|
||||||
|
{"refs/heads/master", []string{"latest"}},
|
||||||
|
{"refs/tags/0.9.0", []string{"0.9", "0.9.0"}},
|
||||||
|
{"refs/tags/1.0.0", []string{"1", "1.0", "1.0.0"}},
|
||||||
|
{"refs/tags/v1.0.0", []string{"1", "1.0", "1.0.0"}},
|
||||||
|
{"refs/tags/v1.0.0-alpha.1", []string{"1.0.0-alpha.1"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tags, err := DefaultTags(test.Before)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
got, want := tags, test.After
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("Got tag %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultTagsError(t *testing.T) {
|
||||||
|
var tests = []string{
|
||||||
|
"refs/tags/x1.0.0",
|
||||||
|
"refs/tags/20190203",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
_, err := DefaultTags(test)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expect tag error for %s", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDefaultTagSuffix(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
Before string
|
||||||
|
Suffix string
|
||||||
|
After []string
|
||||||
|
}{
|
||||||
|
// without suffix
|
||||||
|
{
|
||||||
|
After: []string{"latest"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Before: "refs/tags/v1.0.0",
|
||||||
|
After: []string{
|
||||||
|
"1",
|
||||||
|
"1.0",
|
||||||
|
"1.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// with suffix
|
||||||
|
{
|
||||||
|
Suffix: "linux-amd64",
|
||||||
|
After: []string{"linux-amd64"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Before: "refs/tags/v1.0.0",
|
||||||
|
Suffix: "linux-amd64",
|
||||||
|
After: []string{
|
||||||
|
"1-linux-amd64",
|
||||||
|
"1.0-linux-amd64",
|
||||||
|
"1.0.0-linux-amd64",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{"nanoserver"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Before: "refs/tags/v1.9.2",
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{
|
||||||
|
"1-nanoserver",
|
||||||
|
"1.9-nanoserver",
|
||||||
|
"1.9.2-nanoserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Before: "refs/tags/v18.06.0",
|
||||||
|
Suffix: "nanoserver",
|
||||||
|
After: []string{
|
||||||
|
"18-nanoserver",
|
||||||
|
"18.06-nanoserver",
|
||||||
|
"18.06.0-nanoserver",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
tag, err := DefaultTagSuffix(test.Before, test.Suffix)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
got, want := tag, test.After
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("Got tag %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_stripHeadPrefix(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ref string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
args: args{
|
||||||
|
ref: "refs/heads/master",
|
||||||
|
},
|
||||||
|
want: "master",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
if got := stripHeadPrefix(tt.args.ref); got != tt.want {
|
||||||
|
t.Errorf("stripHeadPrefix() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUseDefaultTag(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ref string
|
||||||
|
defaultBranch string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "latest tag for default branch",
|
||||||
|
args: args{
|
||||||
|
ref: "refs/heads/master",
|
||||||
|
defaultBranch: "master",
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "build from tags",
|
||||||
|
args: args{
|
||||||
|
ref: "refs/tags/v1.0.0",
|
||||||
|
defaultBranch: "master",
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "skip build for not default branch",
|
||||||
|
args: args{
|
||||||
|
ref: "refs/heads/develop",
|
||||||
|
defaultBranch: "master",
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
if got := UseDefaultTag(tt.args.ref, tt.args.defaultBranch); got != tt.want {
|
||||||
|
t.Errorf("%q. UseDefaultTag() = %v, want %v", tt.name, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
renovate.json
Normal file
4
renovate.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": ["github>thegeeklab/renovate-presets"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user