Compare commits

..

No commits in common. "main" and "v2.1.0" have entirely different histories.
main ... v2.1.0

45 changed files with 1318 additions and 729 deletions

394
.drone.jsonnet Normal file
View File

@ -0,0 +1,394 @@
local PipelineTest = {
kind: 'pipeline',
image_pull_secrets: ['docker_config'],
name: 'test',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'staticcheck',
image: 'golang:1.18',
commands: [
'go run honnef.co/go/tools/cmd/staticcheck ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'lint',
image: 'golang:1.18',
commands: [
'go run golang.org/x/lint/golint -set_exit_status ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'vet',
image: 'golang:1.18',
commands: [
'go vet ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'test',
image: 'golang:1.18',
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.18.x',
commands: [
'[ -z "${DRONE_TAG}" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}',
'mkdir -p release/',
"xgo -ldflags \"-s -w -X main.version=$BUILD_VERSION\" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm-7,linux/arm64' -out drone-yaml .",
'mv /build/* /drone/src/release/',
'ls -l /drone/src/release/',
],
},
{
name: 'executable',
image: 'alpine',
commands: [
'$(find release/ -executable -type f | grep drone-yaml-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: '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: {
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.18',
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-yaml',
],
},
{
name: 'dryrun',
image: 'thegeeklab/drone-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: 'thegeeklab/drone-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: 'thegeeklab/drone-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 PipelineDocs = {
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: 'node:lts-alpine',
commands: [
'npm install -g spellchecker-cli',
"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: 'plugins/gh-pages',
settings: {
username: { from_secret: 'github_username' },
password: { from_secret: 'github_token' },
pages_directory: '_docs/',
target_branch: 'docs',
},
when: {
ref: ['refs/heads/main'],
},
},
],
depends_on: [
'build-binaries',
'build-container-amd64',
'build-container-arm64',
'build-container-arm',
],
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: 'Custom Drone YAML formatter',
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' },
roomid: { from_secret: 'matrix_roomid' },
template: 'Status: **{{ build.Status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.Link }}){{#if build.Branch}} ({{ build.Branch }}){{/if}} by {{ commit.Author }}<br/> Message: {{ commit.Message.Title }}',
username: { from_secret: 'matrix_username' },
password: { from_secret: 'matrix_password' },
},
when: {
status: ['success', 'failure'],
},
},
],
depends_on: [
'docs',
],
trigger: {
ref: ['refs/heads/main', 'refs/tags/**'],
status: ['success', 'failure'],
},
};
[
PipelineTest,
PipelineBuildBinaries,
PipelineBuildContainer(arch='amd64'),
PipelineBuildContainer(arch='arm64'),
PipelineBuildContainer(arch='arm'),
PipelineDocs,
PipelineNotifications,
]

534
.drone.yml Normal file
View File

@ -0,0 +1,534 @@
---
kind: pipeline
name: test
platform:
os: linux
arch: amd64
steps:
- name: staticcheck
image: golang:1.18
commands:
- go run honnef.co/go/tools/cmd/staticcheck ./...
volumes:
- name: gopath
path: /go
- name: lint
image: golang:1.18
commands:
- go run golang.org/x/lint/golint -set_exit_status ./...
volumes:
- name: gopath
path: /go
- name: vet
image: golang:1.18
commands:
- go vet ./...
volumes:
- name: gopath
path: /go
- name: test
image: golang:1.18
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.18.x
commands:
- "[ -z \"${DRONE_TAG}\" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}"
- mkdir -p release/
- xgo -ldflags "-s -w -X main.version=$BUILD_VERSION" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm-7,linux/arm64' -out drone-yaml .
- mv /build/* /drone/src/release/
- ls -l /drone/src/release/
- name: executable
image: alpine
commands:
- $(find release/ -executable -type f | grep drone-yaml-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: 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:
- 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.18
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-yaml
- name: dryrun
image: thegeeklab/drone-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: thegeeklab/drone-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: thegeeklab/drone-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.18
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-yaml
- name: dryrun
image: thegeeklab/drone-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: thegeeklab/drone-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: thegeeklab/drone-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: build-container-arm
platform:
os: linux
arch: arm
steps:
- name: build
image: golang:1.18
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/arm/drone-yaml
- name: dryrun
image: thegeeklab/drone-docker:19
settings:
config:
from_secret: docker_config
dockerfile: docker/Dockerfile.arm
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: thegeeklab/drone-docker:19
settings:
auto_tag: true
auto_tag_suffix: arm
config:
from_secret: docker_config
dockerfile: docker/Dockerfile.arm
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: thegeeklab/drone-docker:19
settings:
auto_tag: true
auto_tag_suffix: arm
config:
from_secret: docker_config
dockerfile: docker/Dockerfile.arm
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: 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: node:lts-alpine
commands:
- npm install -g spellchecker-cli
- 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: plugins/gh-pages
settings:
pages_directory: _docs/
password:
from_secret: github_token
target_branch: docs
username:
from_secret: github_username
when:
ref:
- refs/heads/main
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
depends_on:
- build-binaries
- build-container-amd64
- build-container-arm64
- build-container-arm
---
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: Custom Drone YAML formatter
PUSHRM_TARGET: thegeeklab/${DRONE_REPO_NAME}
when:
status:
- success
- name: pushrm-quay
image: chko/docker-pushrm:1
environment:
APIKEY__QUAY_IO:
from_secret: quay_token
PUSHRM_FILE: README.md
PUSHRM_TARGET: quay.io/thegeeklab/${DRONE_REPO_NAME}
when:
status:
- success
- name: matrix
image: thegeeklab/drone-matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
template: "Status: **{{ build.Status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.Link }}){{#if build.Branch}} ({{ build.Branch }}){{/if}} by {{ commit.Author }}<br/> Message: {{ commit.Message.Title }}"
username:
from_secret: matrix_username
when:
status:
- success
- failure
image_pull_secrets:
- docker_config
trigger:
ref:
- refs/heads/main
- refs/tags/**
status:
- success
- failure
depends_on:
- docs
---
kind: signature
hmac: 25fac6a51457126375ef3ab41ceeaa46bebe5160da848528d47ee0ae395db561
...

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
/dist/
/release/ /release/
/drone-yaml* /drone-yaml*

View File

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

View File

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

101
Makefile
View File

@ -1,101 +0,0 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.5.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.54.2
EXECUTABLE := drone-yaml
DIST := dist
DIST_DIRS := $(DIST)
IMPORT := github.com/thegeeklab/$(EXECUTABLE)
GO ?= go
CWD ?= $(shell pwd)
PACKAGES ?= $(shell go list ./...)
SOURCES ?= $(shell find . -name "*.go" -type f)
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@$(GOFUMPT_PACKAGE_VERSION)
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_PACKAGE_VERSION)
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GENERATE ?=
XGO_VERSION := go-1.20.x
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
TARGETOS ?= linux
TARGETARCH ?= amd64
ifneq ("$(TARGETVARIANT)","")
GOARM ?= $(subst v,,$(TARGETVARIANT))
endif
TAGS ?= netgo
ifndef VERSION
ifneq ($(DRONE_TAG),)
VERSION ?= $(subst v,,$(DRONE_TAG))
else
VERSION ?= $(shell git rev-parse --short HEAD)
endif
endif
ifndef DATE
DATE := $(shell date -u +"%Y-%m-%dT%H:%M:%S%z")
endif
LDFLAGS += -s -w -X "main.BuildVersion=$(VERSION)" -X "main.BuildDate=$(DATE)"
.PHONY: all
all: clean build
.PHONY: clean
clean:
$(GO) clean -i ./...
rm -rf $(DIST_DIRS)
.PHONY: fmt
fmt:
$(GO) run $(GOFUMPT_PACKAGE) -extra -w $(SOURCES)
.PHONY: golangci-lint
golangci-lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
.PHONY: lint
lint: golangci-lint
.PHONY: generate
generate:
$(GO) generate $(GENERATE)
.PHONY: test
test:
$(GO) test -v -coverprofile coverage.out $(PACKAGES)
.PHONY: build
build: $(DIST)/$(EXECUTABLE)
$(DIST)/$(EXECUTABLE): $(SOURCES)
GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) GOARM=$(GOARM) $(GO) build -v -tags '$(TAGS)' -ldflags '-extldflags "-static" $(LDFLAGS)' -o $@ ./cmd/$(EXECUTABLE)
$(DIST_DIRS):
mkdir -p $(DIST_DIRS)
.PHONY: xgo
xgo: | $(DIST_DIRS)
$(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -v -ldflags '-extldflags "-static" $(LDFLAGS)' -tags '$(TAGS)' -targets '$(XGO_TARGETS)' -out $(EXECUTABLE) --pkg cmd/$(EXECUTABLE) .
cp /build/* $(CWD)/$(DIST)
ls -l $(CWD)/$(DIST)
.PHONY: checksum
checksum:
cd $(DIST); $(foreach file,$(wildcard $(DIST)/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
ls -l $(CWD)/$(DIST)
.PHONY: release
release: xgo checksum
.PHONY: deps
deps:
$(GO) mod download
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(XGO_PACKAGE)

View File

@ -1,6 +1,6 @@
# drone-yaml # drone-yaml
DISCONTINUED: Custom Drone YAML formatter Custom Drone YAML formatter
[![Build Status](https://img.shields.io/drone/build/thegeeklab/drone-yaml?logo=drone&server=https%3A%2F%2Fdrone.thegeeklab.de)](https://drone.thegeeklab.de/thegeeklab/drone-yaml) [![Build Status](https://img.shields.io/drone/build/thegeeklab/drone-yaml?logo=drone&server=https%3A%2F%2Fdrone.thegeeklab.de)](https://drone.thegeeklab.de/thegeeklab/drone-yaml)
[![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/drone-yaml) [![Docker Hub](https://img.shields.io/badge/dockerhub-latest-blue.svg?logo=docker&logoColor=white)](https://hub.docker.com/r/thegeeklab/drone-yaml)
@ -10,13 +10,12 @@ DISCONTINUED: Custom Drone YAML formatter
[![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/drone-yaml) [![Source: GitHub](https://img.shields.io/badge/source-github-blue.svg?logo=github&logoColor=white)](https://github.com/thegeeklab/drone-yaml)
[![License: Apache-2.0](https://img.shields.io/github/license/thegeeklab/drone-yaml)](https://github.com/thegeeklab/drone-yaml/blob/main/LICENSE) [![License: Apache-2.0](https://img.shields.io/github/license/thegeeklab/drone-yaml)](https://github.com/thegeeklab/drone-yaml/blob/main/LICENSE)
> **DISCONTINUED:** As I don't use Drone CI anymore, this project is unmaintained. If you are interested in a free and open source CI system check out [Woodpecker CI](https://woodpecker-ci.org/). Custom linter and formatter for the [Drone](https://github.com/drone/drone) YAML configuration file format. You can find the full documentation at You can find the full documentation at [https://drone-plugin-index.geekdocs.de](https://drone-plugin-index.geekdocs.de/tools/drone-yaml).
Custom linter and formatter for the [Drone](https://github.com/drone/drone) YAML configuration file format. You can find the full documentation at [https://drone-plugin-index.geekdocs.de](https://drone-plugin-index.geekdocs.de/tools/drone-yaml).
## Contributors ## Contributors
Special thanks to all [contributors](https://github.com/thegeeklab/drone-yaml/graphs/contributors). If you would like to contribute, please see the [instructions](https://github.com/thegeeklab/drone-yaml/blob/main/CONTRIBUTING.md). Special thanks goes to all [contributors](https://github.com/thegeeklab/drone-yaml/graphs/contributors). If you would like to contribute,
please see the [instructions](https://github.com/thegeeklab/drone-yaml/blob/main/CONTRIBUTING.md).
## License ## License

View File

@ -27,7 +27,7 @@ export GOARCH=amd64
export CGO_ENABLED=0 export CGO_ENABLED=0
export GO111MODULE=on export GO111MODULE=on
make build go build -v -a -tags netgo -o release/linux/amd64/drone-yaml
``` ```
Build the Docker image with the following command: Build the Docker image with the following command:
@ -38,7 +38,8 @@ docker build --file docker/Dockerfile.amd64 --tag thegeeklab/drone-yaml .
## Usage ## Usage
{{< hint type=important >}} {{< hint warning >}}
**Note**\
Be aware that the tool only supports configuration files for the Drone Docker runner! Be aware that the tool only supports configuration files for the Drone Docker runner!
{{< /hint >}} {{< /hint >}}

View File

@ -1,14 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.20@sha256:741d6f9bcab778441efe05c8e4369d4f8ff56c9a635a97d77f55d8b0ec62f907 as build FROM alpine:3.15@sha256:f22945d45ee2eb4dd463ed5a431d9f04fcd80ca768bb1acf898d91ce51f7bf04
ARG TARGETOS
ARG TARGETARCH
ADD . /src
WORKDIR /src
RUN make build
FROM alpine:3.18@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>" LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>" LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
@ -17,5 +7,5 @@ LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-yaml" LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-yaml" LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-yaml"
COPY --from=build /src/dist/drone-yaml /bin/drone-yaml ADD release/amd64/drone-yaml /bin/
ENTRYPOINT [ "/bin/drone-yaml" ] ENTRYPOINT [ "/bin/drone-yaml" ]

11
docker/Dockerfile.arm Normal file
View File

@ -0,0 +1,11 @@
FROM arm32v7/alpine:3.15@sha256:5d4a549d1a0d42c790cb7b848485404e6d32a1f6256d6174adda83c300a0456b
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.title="drone-yaml"
LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-yaml"
ADD release/arm/drone-yaml /bin/
ENTRYPOINT [ "/bin/drone-yaml" ]

11
docker/Dockerfile.arm64 Normal file
View File

@ -0,0 +1,11 @@
FROM arm64v8/alpine:3.15@sha256:d72e2d383f2d5fb1e8186ebfd1fbb22a87c04f52ac12fc379d21abb368d373df
LABEL maintainer="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.authors="Robert Kaussow <mail@thegeeklab.de>"
LABEL org.opencontainers.image.title="drone-yaml"
LABEL org.opencontainers.image.url="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.source="https://github.com/thegeeklab/drone-yaml"
LABEL org.opencontainers.image.documentation="https://github.com/thegeeklab/drone-yaml"
ADD release/arm64/drone-yaml /bin/
ENTRYPOINT [ "/bin/drone-yaml" ]

24
docker/manifest-quay.tmpl Normal file
View File

@ -0,0 +1,24 @@
image: quay.io/thegeeklab/drone-yaml:{{#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-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}amd64
platform:
architecture: amd64
os: linux
- image: quay.io/thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm64
platform:
architecture: arm64
os: linux
variant: v8
- image: quay.io/thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm
platform:
architecture: arm
os: linux
variant: v7

24
docker/manifest.tmpl Normal file
View File

@ -0,0 +1,24 @@
image: thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
- image: thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}amd64
platform:
architecture: amd64
os: linux
- image: thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm64
platform:
architecture: arm64
os: linux
variant: v8
- image: thegeeklab/drone-yaml:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}arm
platform:
architecture: arm
os: linux
variant: v7

21
go.mod
View File

@ -1,18 +1,27 @@
module github.com/drone/drone-yaml module github.com/drone/drone-yaml
go 1.20 go 1.18
require ( require (
github.com/alecthomas/kingpin/v2 v2.3.2 github.com/bmatcuk/doublestar/v4 v4.0.2
github.com/bmatcuk/doublestar/v4 v4.6.0 github.com/docker/go-units v0.4.0
github.com/docker/go-units v0.5.0 github.com/google/go-cmp v0.5.7
github.com/google/go-cmp v0.5.9 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
honnef.co/go/tools v0.3.0
) )
require ( require (
github.com/BurntSushi/toml v1.0.0 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f // indirect
golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
) )

52
go.sum
View File

@ -1,15 +1,18 @@
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc= github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA=
github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmatcuk/doublestar/v4 v4.0.2/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -18,14 +21,39 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb h1:fP6C8Xutcp5AlakmT/SkQot0pMicROAsEX7OfNPuG10=
golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f h1:rlezHXNlxYWvBCzNses9Dlc7nGFaNMJeqLolcmQSSZY=
golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a h1:ofrrl6c6NG5/IOSx/R1cyiQxxjqlur0h/TvbUhkH0II=
golang.org/x/tools v0.1.11-0.20220316014157-77aa08bb151a/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= honnef.co/go/tools v0.3.0 h1:2LdYUZ7CIxnYgskbUZfY7FPggmqnh6shBqfWa8Tn3XU=
honnef.co/go/tools v0.3.0/go.mod h1:vlRD9XErLMGT+mDuofSr0mMMquscM/1nQqtRSsh6m70=

View File

@ -6,15 +6,16 @@ package main
import ( import (
"bytes" "bytes"
"io" "io"
"io/ioutil"
"os" "os"
"github.com/alecthomas/kingpin/v2"
"github.com/drone/drone-yaml/yaml" "github.com/drone/drone-yaml/yaml"
"github.com/drone/drone-yaml/yaml/linter" "github.com/drone/drone-yaml/yaml/linter"
"github.com/drone/drone-yaml/yaml/pretty" "github.com/drone/drone-yaml/yaml/pretty"
"gopkg.in/alecthomas/kingpin.v2"
) )
//nolint:gochecknoglobals
var ( var (
format = kingpin.Command("fmt", "format the yaml file") format = kingpin.Command("fmt", "format the yaml file")
formatSave = format.Flag("save", "save result to source").Short('s').Bool() formatSave = format.Flag("save", "save result to source").Short('s').Bool()
@ -25,8 +26,6 @@ var (
lintFile = lint.Arg("source", "source file location").Default(".drone.yml").File() lintFile = lint.Arg("source", "source file location").Default(".drone.yml").File()
) )
const DefaultFilePerm = 0o640
func main() { func main() {
switch kingpin.Parse() { switch kingpin.Parse() {
case format.FullCommand(): case format.FullCommand():
@ -38,7 +37,6 @@ func main() {
func runFormat() error { func runFormat() error {
f := *formatFile f := *formatFile
m, err := yaml.Parse(f) m, err := yaml.Parse(f)
if err != nil { if err != nil {
return err return err
@ -48,28 +46,23 @@ func runFormat() error {
pretty.Print(b, m) pretty.Print(b, m)
if *formatSave { if *formatSave {
return os.WriteFile(f.Name(), b.Bytes(), DefaultFilePerm) return ioutil.WriteFile(f.Name(), b.Bytes(), 0644)
} }
_, err = io.Copy(os.Stderr, b) _, err = io.Copy(os.Stderr, b)
return err return err
} }
func runLint() error { func runLint() error {
f := *lintFile f := *lintFile
m, err := yaml.Parse(f) m, err := yaml.Parse(f)
if err != nil { if err != nil {
return err return err
} }
for _, r := range m.Resources { for _, r := range m.Resources {
err := linter.Lint(r, *lintPriv) err := linter.Lint(r, *lintPriv)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }

4
renovate.json Normal file
View File

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

8
tools.go Normal file
View File

@ -0,0 +1,8 @@
// +build tools
package tools
import (
_ "golang.org/x/lint/golint"
_ "honnef.co/go/tools/cmd/staticcheck"
)

View File

@ -29,18 +29,15 @@ type (
// UnmarshalYAML implements yaml unmarshalling. // UnmarshalYAML implements yaml unmarshalling.
func (b *Build) UnmarshalYAML(unmarshal func(interface{}) error) error { func (b *Build) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(build) d := new(build)
err := unmarshal(&d.Image) err := unmarshal(&d.Image)
if err != nil { if err != nil {
err = unmarshal(d) err = unmarshal(d)
} }
b.Args = d.Args b.Args = d.Args
b.CacheFrom = d.CacheFrom b.CacheFrom = d.CacheFrom
b.Context = d.Context b.Context = d.Context
b.Dockerfile = d.Dockerfile b.Dockerfile = d.Dockerfile
b.Labels = d.Labels b.Labels = d.Labels
b.Image = d.Image b.Image = d.Image
return err return err
} }

View File

@ -32,15 +32,12 @@ func (c *Condition) Match(v string) bool {
if c.Excludes(v) { if c.Excludes(v) {
return false return false
} }
if c.Includes(v) { if c.Includes(v) {
return true return true
} }
if len(c.Include) == 0 { if len(c.Include) == 0 {
return true return true
} }
return false return false
} }
@ -52,7 +49,6 @@ func (c *Condition) Includes(v string) bool {
return true return true
} }
} }
return false return false
} }
@ -64,18 +60,14 @@ func (c *Condition) Excludes(v string) bool {
return true return true
} }
} }
return false return false
} }
// UnmarshalYAML implements yml unmarshalling. // UnmarshalYAML implements yml unmarshalling.
func (c *Condition) UnmarshalYAML(unmarshal func(interface{}) error) error { func (c *Condition) UnmarshalYAML(unmarshal func(interface{}) error) error {
var ( var out1 string
out1 string var out2 []string
out2 []string var out3 = struct {
)
out3 := struct {
Include []string Include []string
Exclude []string Exclude []string
}{} }{}
@ -83,20 +75,17 @@ func (c *Condition) UnmarshalYAML(unmarshal func(interface{}) error) error {
err := unmarshal(&out1) err := unmarshal(&out1)
if err == nil { if err == nil {
c.Include = []string{out1} c.Include = []string{out1}
return nil return nil
} }
_ = unmarshal(&out2) unmarshal(&out2)
_ = unmarshal(&out3) unmarshal(&out3)
out3.Include = append( c.Exclude = out3.Exclude
c.Include = append(
out3.Include, out3.Include,
out2..., out2...,
) )
c.Exclude = out3.Exclude
c.Include = out3.Include
return nil return nil
} }

View File

@ -5,8 +5,6 @@ package yaml
import "errors" import "errors"
var ErrInvlaidCronBranch = errors.New("yaml: invalid cron branch")
type ( type (
// Cron is a resource that defines a cron job, used // Cron is a resource that defines a cron job, used
// to execute pipelines at scheduled intervals. // to execute pipelines at scheduled intervals.
@ -23,7 +21,7 @@ type (
CronSpec struct { CronSpec struct {
Schedule string `json:"schedule,omitempty"` Schedule string `json:"schedule,omitempty"`
Branch string `json:"branch,omitempty"` Branch string `json:"branch,omitempty"`
Deployment CronDeployment `json:"deployment,omitempty" yaml:"deployment"` Deploy CronDeployment `json:"deployment,omitempty" yaml:"deployment"`
} }
// CronDeployment defines a cron job deployment. // CronDeployment defines a cron job deployment.
@ -42,7 +40,7 @@ func (c *Cron) GetKind() string { return c.Kind }
func (c Cron) Validate() error { func (c Cron) Validate() error {
switch { switch {
case c.Spec.Branch == "": case c.Spec.Branch == "":
return ErrInvlaidCronBranch return errors.New("yaml: invalid cron branch")
default: default:
return nil return nil
} }

View File

@ -9,45 +9,38 @@ type (
// to a secret. // to a secret.
Variable struct { Variable struct {
Value string `json:"value,omitempty"` Value string `json:"value,omitempty"`
FromSecret string `json:"from_secret,omitempty" yaml:"from_secret"` Secret string `json:"from_secret,omitempty" yaml:"from_secret"`
} }
// variable is a tempoary type used to unmarshal // variable is a tempoary type used to unmarshal
// variables with references to secrets. // variables with references to secrets.
variable struct { variable struct {
Value string Value string
FromSecret string `yaml:"from_secret"` Secret string `yaml:"from_secret"`
} }
) )
// UnmarshalYAML implements yaml unmarshalling. // UnmarshalYAML implements yaml unmarshalling.
func (v *Variable) UnmarshalYAML(unmarshal func(interface{}) error) error { func (v *Variable) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(variable) d := new(variable)
err := unmarshal(&d.Value) err := unmarshal(&d.Value)
if err != nil { if err != nil {
err = unmarshal(d) err = unmarshal(d)
} }
v.Value = d.Value v.Value = d.Value
v.FromSecret = d.FromSecret v.Secret = d.Secret
return err return err
} }
// MarshalYAML implements yaml marshalling. // MarshalYAML implements yaml marshalling.
func (v *Variable) MarshalYAML() (interface{}, error) { func (v *Variable) MarshalYAML() (interface{}, error) {
if v.FromSecret != "" { if v.Secret != "" {
m := map[string]interface{}{} m := map[string]interface{}{}
m["from_secret"] = v.FromSecret m["from_secret"] = v.Secret
return m, nil return m, nil
} }
if v.Value != "" { if v.Value != "" {
return v.Value, nil return v.Value, nil
} }
//nolint:nilnil
return nil, nil return nil, nil
} }

View File

@ -14,7 +14,7 @@ import (
var ErrDuplicatePipelineName = errors.New("linter: duplicate pipeline names") var ErrDuplicatePipelineName = errors.New("linter: duplicate pipeline names")
// ErrMissingPipelineDependency is returned when a Pipeline // ErrMissingPipelineDependency is returned when a Pipeline
// defines dependencies that are invalid or unknown. // defines dependencies that are invlid or unknown.
var ErrMissingPipelineDependency = errors.New("linter: invalid or unknown pipeline dependency") var ErrMissingPipelineDependency = errors.New("linter: invalid or unknown pipeline dependency")
// ErrCyclicalPipelineDependency is returned when a Pipeline // ErrCyclicalPipelineDependency is returned when a Pipeline
@ -27,13 +27,12 @@ var ErrCyclicalPipelineDependency = errors.New("linter: cyclical pipeline depend
var ErrPipelineSelfDependency = errors.New("linter: pipeline cannot have a dependency on itself") var ErrPipelineSelfDependency = errors.New("linter: pipeline cannot have a dependency on itself")
// Manifest performs lint operations for a manifest. // Manifest performs lint operations for a manifest.
func Manifest(manifest *yaml.Manifest) error { func Manifest(manifest *yaml.Manifest, trusted bool) error {
return checkPipelines(manifest) return checkPipelines(manifest, trusted)
} }
func checkPipelines(manifest *yaml.Manifest) error { func checkPipelines(manifest *yaml.Manifest, trusted bool) error {
names := map[string]struct{}{} names := map[string]struct{}{}
for _, resource := range manifest.Resources { for _, resource := range manifest.Resources {
switch v := resource.(type) { switch v := resource.(type) {
case *yaml.Pipeline: case *yaml.Pipeline:
@ -41,25 +40,19 @@ func checkPipelines(manifest *yaml.Manifest) error {
if ok { if ok {
return ErrDuplicatePipelineName return ErrDuplicatePipelineName
} }
names[v.Name] = struct{}{} names[v.Name] = struct{}{}
err := checkPipelineDeps(v, names) err := checkPipelineDeps(v, names)
if err != nil { if err != nil {
return err return err
} }
if (v.Kind == "pipeline" || v.Kind == "") && (v.Type == "" || v.Type == "docker") { if (v.Kind == "pipeline" || v.Kind == "") && (v.Type == "" || v.Type == "docker") {
err = checkPlatform(v.Platform) err = checkPlatform(v.Platform)
if err != nil { if err != nil {
return err return err
} }
} }
default:
continue
} }
} }
return nil return nil
} }
@ -69,11 +62,9 @@ func checkPipelineDeps(pipeline *yaml.Pipeline, deps map[string]struct{}) error
if !ok { if !ok {
return ErrMissingPipelineDependency return ErrMissingPipelineDependency
} }
if pipeline.Name == dep { if pipeline.Name == dep {
return ErrPipelineSelfDependency return ErrPipelineSelfDependency
} }
} }
return nil return nil
} }

View File

@ -10,49 +10,29 @@ import (
"github.com/drone/drone-yaml/yaml" "github.com/drone/drone-yaml/yaml"
) )
//nolint:gochecknoglobals var os = map[string]struct{}{
var (
os = map[string]struct{}{
"linux": {}, "linux": {},
"windows": {}, "windows": {},
} }
arch = map[string]struct{}{
var arch = map[string]struct{}{
"arm": {}, "arm": {},
"arm64": {}, "arm64": {},
"amd64": {}, "amd64": {},
} }
)
var ( // ErrDuplicateStepName is returned when two Pipeline steps
// ErrDuplicateStepName is returned when two Pipeline steps // have the same name.
// have the same name. var ErrDuplicateStepName = errors.New("linter: duplicate step names")
ErrDuplicateStepName = errors.New("linter: duplicate step names")
// ErrMissingDependency is returned when a Pipeline step // ErrMissingDependency is returned when a Pipeline step
// defines dependencies that are invalid or unknown. // defines dependencies that are invlid or unknown.
ErrMissingDependency = errors.New("linter: invalid or unknown step dependency") var ErrMissingDependency = errors.New("linter: invalid or unknown step dependency")
// ErrCyclicalDependency is returned when a Pipeline step // ErrCyclicalDependency is returned when a Pipeline step
// defines a cyclical dependency, which would result in an // defines a cyclical dependency, which would result in an
// infinite execution loop. // infinite execution loop.
ErrCyclicalDependency = errors.New("linter: cyclical step dependency detected") var ErrCyclicalDependency = errors.New("linter: cyclical step dependency detected")
ErrUnsupportedOS = errors.New("linter: unsupported os")
ErrUnsupportedArch = errors.New("linter: unsupported architecture")
ErrInvalidImage = errors.New("linter: invalid or missing image")
ErrInvalidBuildImage = errors.New("linter: invalid or missing build image")
ErrInvalidName = errors.New("linter: invalid or missing name")
ErrPrivilegedNotAllowed = errors.New("linter: untrusted repositories cannot enable privileged mode")
ErrMountNotAllowed = errors.New("linter: untrusted repositories cannot mount devices")
ErrDNSNotAllowed = errors.New("linter: untrusted repositories cannot configure dns")
ErrDNSSearchNotAllowed = errors.New("linter: untrusted repositories cannot configure dns_search")
ErrExtraHostsNotAllowed = errors.New("linter: untrusted repositories cannot configure extra_hosts")
ErrNetworkModeNotAllowed = errors.New("linter: untrusted repositories cannot configure network_mode")
ErrInvalidVolumeName = errors.New("linter: invalid volume name")
ErrHostPortNotAllowed = errors.New("linter: untrusted repositories cannot map to a host port")
ErrHostVolumeNotAllowed = errors.New("linter: untrusted repositories cannot mount host volumes")
ErrTempVolumeNotAllowed = errors.New("linter: untrusted repositories cannot mount in-memory volumes")
)
// Lint performs lint operations for a resource. // Lint performs lint operations for a resource.
func Lint(resource yaml.Resource, trusted bool) error { func Lint(resource yaml.Resource, trusted bool) error {
@ -77,23 +57,19 @@ func checkPipeline(pipeline *yaml.Pipeline, trusted bool) error {
if err != nil { if err != nil {
return err return err
} }
err = checkPlatform(pipeline.Platform) err = checkPlatform(pipeline.Platform)
if err != nil { if err != nil {
return err return err
} }
names := map[string]struct{}{} names := map[string]struct{}{}
if !pipeline.Clone.Disable { if !pipeline.Clone.Disable {
names["clone"] = struct{}{} names["clone"] = struct{}{}
} }
for _, container := range pipeline.Steps { for _, container := range pipeline.Steps {
_, ok := names[container.Name] _, ok := names[container.Name]
if ok { if ok {
return ErrDuplicateStepName return ErrDuplicateStepName
} }
names[container.Name] = struct{}{} names[container.Name] = struct{}{}
err := checkContainer(container, trusted) err := checkContainer(container, trusted)
@ -106,13 +82,11 @@ func checkPipeline(pipeline *yaml.Pipeline, trusted bool) error {
return err return err
} }
} }
for _, container := range pipeline.Services { for _, container := range pipeline.Services {
_, ok := names[container.Name] _, ok := names[container.Name]
if ok { if ok {
return ErrDuplicateStepName return ErrDuplicateStepName
} }
names[container.Name] = struct{}{} names[container.Name] = struct{}{}
err := checkContainer(container, trusted) err := checkContainer(container, trusted)
@ -120,7 +94,6 @@ func checkPipeline(pipeline *yaml.Pipeline, trusted bool) error {
return err return err
} }
} }
return nil return nil
} }
@ -128,17 +101,15 @@ func checkPlatform(platform yaml.Platform) error {
if v := platform.OS; v != "" { if v := platform.OS; v != "" {
_, ok := os[v] _, ok := os[v]
if !ok { if !ok {
return fmt.Errorf("%w: %s", ErrUnsupportedOS, v) return fmt.Errorf("linter: unsupported os: %s", v)
} }
} }
if v := platform.Arch; v != "" { if v := platform.Arch; v != "" {
_, ok := arch[v] _, ok := arch[v]
if !ok { if !ok {
return fmt.Errorf("%w: %s", ErrUnsupportedArch, v) return fmt.Errorf("linter: unsupported architecture: %s", v)
} }
} }
return nil return nil
} }
@ -147,50 +118,39 @@ func checkContainer(container *yaml.Container, trusted bool) error {
if err != nil { if err != nil {
return err return err
} }
if container.Build == nil && container.Image == "" { if container.Build == nil && container.Image == "" {
return ErrInvalidImage return errors.New("linter: invalid or missing image")
} }
if container.Build != nil && container.Build.Image == "" { if container.Build != nil && container.Build.Image == "" {
return ErrInvalidBuildImage return errors.New("linter: invalid or missing build image")
} }
if container.Name == "" { if container.Name == "" {
return ErrInvalidName return errors.New("linter: invalid or missing name")
} }
if trusted && container.Privileged { if trusted && container.Privileged {
return ErrPrivilegedNotAllowed return errors.New("linter: untrusted repositories cannot enable privileged mode")
} }
if trusted && len(container.Devices) > 0 { if trusted && len(container.Devices) > 0 {
return ErrMountNotAllowed return errors.New("linter: untrusted repositories cannot mount devices")
} }
if trusted && len(container.DNS) > 0 { if trusted && len(container.DNS) > 0 {
return ErrDNSNotAllowed return errors.New("linter: untrusted repositories cannot configure dns")
} }
if trusted && len(container.DNSSearch) > 0 { if trusted && len(container.DNSSearch) > 0 {
return ErrDNSSearchNotAllowed return errors.New("linter: untrusted repositories cannot configure dns_search")
} }
if trusted && len(container.ExtraHosts) > 0 { if trusted && len(container.ExtraHosts) > 0 {
return ErrExtraHostsNotAllowed return errors.New("linter: untrusted repositories cannot configure extra_hosts")
} }
if trusted && len(container.Network) > 0 {
if trusted && len(container.NetworkMode) > 0 { return errors.New("linter: untrusted repositories cannot configure network_mode")
return ErrNetworkModeNotAllowed
} }
for _, mount := range container.Volumes { for _, mount := range container.Volumes {
switch mount.Name { switch mount.Name {
case "workspace", "_workspace", "_docker_socket": case "workspace", "_workspace", "_docker_socket":
return fmt.Errorf("%w: %s", ErrInvalidVolumeName, mount.Name) return fmt.Errorf("linter: invalid volume name: %s", mount.Name)
} }
} }
return nil return nil
} }
@ -201,56 +161,49 @@ func checkPorts(ports []*yaml.Port, trusted bool) error {
return err return err
} }
} }
return nil return nil
} }
func checkPort(port *yaml.Port, trusted bool) error { func checkPort(port *yaml.Port, trusted bool) error {
if trusted && port.Host != 0 { if trusted && port.Host != 0 {
return ErrHostPortNotAllowed return errors.New("linter: untrusted repositories cannot map to a host port")
} }
return nil return nil
} }
func checkVolumes(pipeline *yaml.Pipeline, trusted bool) error { func checkVolumes(pipeline *yaml.Pipeline, trusted bool) error {
for _, volume := range pipeline.Volumes { for _, volume := range pipeline.Volumes {
if volume.Temp != nil { if volume.EmptyDir != nil {
err := checkEmptyDirVolume(volume.Temp, trusted) err := checkEmptyDirVolume(volume.EmptyDir, trusted)
if err != nil { if err != nil {
return err return err
} }
} }
if volume.HostPath != nil {
if volume.Host != nil { err := checkHostPathVolume(volume.HostPath, trusted)
err := checkHostPathVolume(trusted)
if err != nil { if err != nil {
return err return err
} }
} }
switch volume.Name { switch volume.Name {
case "workspace", "_workspace", "_docker_socket": case "workspace", "_workspace", "_docker_socket":
return fmt.Errorf("%w: %s", ErrInvalidVolumeName, volume.Name) return fmt.Errorf("linter: invalid volume name: %s", volume.Name)
} }
} }
return nil return nil
} }
func checkHostPathVolume(trusted bool) error { func checkHostPathVolume(volume *yaml.VolumeHostPath, trusted bool) error {
if trusted { if trusted {
return ErrHostVolumeNotAllowed return errors.New("linter: untrusted repositories cannot mount host volumes")
} }
return nil return nil
} }
func checkEmptyDirVolume(volume *yaml.VolumeEmptyDir, trusted bool) error { func checkEmptyDirVolume(volume *yaml.VolumeEmptyDir, trusted bool) error {
if trusted && volume.Medium == "memory" { if trusted && volume.Medium == "memory" {
return ErrTempVolumeNotAllowed return errors.New("linter: untrusted repositories cannot mount in-memory volumes")
} }
return nil return nil
} }
@ -260,11 +213,9 @@ func checkDeps(container *yaml.Container, deps map[string]struct{}) error {
if !ok { if !ok {
return ErrMissingDependency return ErrMissingDependency
} }
if container.Name == dep { if container.Name == dep {
return ErrCyclicalDependency return ErrCyclicalDependency
} }
} }
return nil return nil
} }

View File

@ -20,8 +20,6 @@ const (
KindSignature = "signature" KindSignature = "signature"
) )
var ErrMarshalNotImplemented = errors.New("yaml: marshal not implemented")
type ( type (
// Manifest is a collection of Drone resources. // Manifest is a collection of Drone resources.
Manifest struct { Manifest struct {
@ -46,7 +44,6 @@ type (
Data []byte `yaml:"-"` Data []byte `yaml:"-"`
} }
//nolint:musttag
resource struct { resource struct {
Version string Version string
Kind string `json:"kind"` Kind string `json:"kind"`
@ -57,22 +54,17 @@ type (
// UnmarshalJSON implement the json.Unmarshaler. // UnmarshalJSON implement the json.Unmarshaler.
func (m *Manifest) UnmarshalJSON(b []byte) error { func (m *Manifest) UnmarshalJSON(b []byte) error {
messages := []json.RawMessage{} messages := []json.RawMessage{}
err := json.Unmarshal(b, &messages) err := json.Unmarshal(b, &messages)
if err != nil { if err != nil {
return err return err
} }
for _, message := range messages { for _, message := range messages {
res := new(resource) res := new(resource)
err := json.Unmarshal(message, res) err := json.Unmarshal(message, res)
if err != nil { if err != nil {
return err return err
} }
var obj Resource var obj Resource
switch res.Kind { switch res.Kind {
case "cron": case "cron":
obj = new(Cron) obj = new(Cron)
@ -85,15 +77,12 @@ func (m *Manifest) UnmarshalJSON(b []byte) error {
default: default:
obj = new(Pipeline) obj = new(Pipeline)
} }
err = json.Unmarshal(message, obj) err = json.Unmarshal(message, obj)
if err != nil { if err != nil {
return err return err
} }
m.Resources = append(m.Resources, obj) m.Resources = append(m.Resources, obj)
} }
return nil return nil
} }
@ -107,19 +96,17 @@ func (m *Manifest) MarshalJSON() ([]byte, error) {
// documents, and MarshalYAML would otherwise attempt to marshal // documents, and MarshalYAML would otherwise attempt to marshal
// as a single Yaml document. Use the Encode method instead. // as a single Yaml document. Use the Encode method instead.
func (m *Manifest) MarshalYAML() (interface{}, error) { func (m *Manifest) MarshalYAML() (interface{}, error) {
return nil, ErrMarshalNotImplemented return nil, errors.New("yaml: marshal not implemented")
} }
// Encode encodes the manifest in Yaml format. // Encode encodes the manifest in Yaml format.
func (m *Manifest) Encode() ([]byte, error) { func (m *Manifest) Encode() ([]byte, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
enc := yaml.NewEncoder(buf) enc := yaml.NewEncoder(buf)
for _, res := range m.Resources { for _, res := range m.Resources {
if err := enc.Encode(res); err != nil { if err := enc.Encode(res); err != nil {
return nil, err return nil, err
} }
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }

View File

@ -9,13 +9,13 @@ type (
// to a secret. // to a secret.
Parameter struct { Parameter struct {
Value interface{} `json:"value,omitempty"` Value interface{} `json:"value,omitempty"`
FromSecret string `json:"from_secret,omitempty" yaml:"from_secret"` Secret string `json:"from_secret,omitempty" yaml:"from_secret"`
} }
// parameter is a tempoary type used to unmarshal // parameter is a tempoary type used to unmarshal
// parameters with references to secrets. // parameters with references to secrets.
parameter struct { parameter struct {
FromSecret string `yaml:"from_secret"` Secret string `yaml:"from_secret"`
} }
) )
@ -23,33 +23,25 @@ type (
func (p *Parameter) UnmarshalYAML(unmarshal func(interface{}) error) error { func (p *Parameter) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(parameter) d := new(parameter)
err := unmarshal(d) err := unmarshal(d)
if err == nil && d.Secret != "" {
if err == nil && d.FromSecret != "" { p.Secret = d.Secret
p.FromSecret = d.FromSecret
return nil return nil
} }
var i interface{} var i interface{}
err = unmarshal(&i) err = unmarshal(&i)
p.Value = i p.Value = i
return err return err
} }
// MarshalYAML implements yaml marshalling. // MarshalYAML implements yaml marshalling.
func (p *Parameter) MarshalYAML() (interface{}, error) { func (p *Parameter) MarshalYAML() (interface{}, error) {
if p.FromSecret != "" { if p.Secret != "" {
m := map[string]interface{}{} m := map[string]interface{}{}
m["from_secret"] = p.FromSecret m["from_secret"] = p.Secret
return m, nil return m, nil
} }
if p.Value != "" { if p.Value != "" {
return p.Value, nil return p.Value, nil
} }
//nolint:nilnil
return nil, nil return nil, nil
} }

View File

@ -14,7 +14,7 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var ErrMissingKind = errors.New("yaml: missing kind attribute") var errorMissingKind = errors.New("yaml: missing kind attribute")
// Parse parses the configuration from io.Reader r. // Parse parses the configuration from io.Reader r.
func Parse(r io.Reader) (*Manifest, error) { func Parse(r io.Reader) (*Manifest, error) {
@ -22,29 +22,23 @@ func Parse(r io.Reader) (*Manifest, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
manifest := new(Manifest) manifest := new(Manifest)
for _, raw := range resources { for _, raw := range resources {
if raw == nil { if raw == nil {
continue continue
} }
resource, err := parseRaw(raw) resource, err := parseRaw(raw)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if resource.GetKind() == "" { if resource.GetKind() == "" {
return nil, ErrMissingKind return nil, errorMissingKind
} }
manifest.Resources = append( manifest.Resources = append(
manifest.Resources, manifest.Resources,
resource, resource,
) )
} }
return manifest, nil return manifest, nil
} }
@ -69,13 +63,11 @@ func ParseFile(p string) (*Manifest, error) {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
return Parse(f) return Parse(f)
} }
func parseRaw(r *RawResource) (Resource, error) { //nolint:ireturn func parseRaw(r *RawResource) (Resource, error) {
var obj Resource var obj Resource
switch r.Kind { switch r.Kind {
case "cron": case "cron":
obj = new(Cron) obj = new(Cron)
@ -88,9 +80,7 @@ func parseRaw(r *RawResource) (Resource, error) { //nolint:ireturn
default: default:
obj = new(Pipeline) obj = new(Pipeline)
} }
err := yaml.Unmarshal(r.Data, obj) err := yaml.Unmarshal(r.Data, obj)
return obj, err return obj, err
} }
@ -98,11 +88,8 @@ func parseRaw(r *RawResource) (Resource, error) { //nolint:ireturn
// io.Reader and returns a slice of raw resources. // io.Reader and returns a slice of raw resources.
func ParseRaw(r io.Reader) ([]*RawResource, error) { func ParseRaw(r io.Reader) ([]*RawResource, error) {
const newline = '\n' const newline = '\n'
var resources []*RawResource
var ( var resource *RawResource
resources []*RawResource
resource *RawResource
)
scanner := bufio.NewScanner(r) scanner := bufio.NewScanner(r)
for scanner.Scan() { for scanner.Scan() {
@ -110,42 +97,34 @@ func ParseRaw(r io.Reader) ([]*RawResource, error) {
if isSeparator(line) { if isSeparator(line) {
resource = nil resource = nil
} }
if resource == nil { if resource == nil {
resource = &RawResource{} resource = &RawResource{}
resources = append(resources, resource) resources = append(resources, resource)
} }
if isSeparator(line) { if isSeparator(line) {
continue continue
} }
if isTerminator(line) { if isTerminator(line) {
break break
} }
if scanner.Err() == io.EOF {
if errors.Is(scanner.Err(), io.EOF) {
break break
} }
resource.Data = append( resource.Data = append(
resource.Data, resource.Data,
line..., line...,
) )
resource.Data = append( resource.Data = append(
resource.Data, resource.Data,
newline, newline,
) )
} }
for _, resource := range resources { for _, resource := range resources {
err := yaml.Unmarshal(resource.Data, resource) err := yaml.Unmarshal(resource.Data, resource)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
return resources, nil return resources, nil
} }
@ -173,7 +152,6 @@ func ParseRawFile(p string) ([]*RawResource, error) {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
return ParseRaw(f) return ParseRaw(f)
} }

View File

@ -16,7 +16,7 @@ type Pipeline struct {
DependsOn []string `json:"depends_on,omitempty" yaml:"depends_on" ` DependsOn []string `json:"depends_on,omitempty" yaml:"depends_on" `
Node map[string]string `json:"node,omitempty" yaml:"node"` Node map[string]string `json:"node,omitempty" yaml:"node"`
Platform Platform `json:"platform,omitempty"` Platform Platform `json:"platform,omitempty"`
ImagePullSecrets []string `json:"image_pull_secrets,omitempty" yaml:"image_pull_secrets"` PullSecrets []string `json:"image_pull_secrets,omitempty" yaml:"image_pull_secrets"`
Services []*Container `json:"services,omitempty"` Services []*Container `json:"services,omitempty"`
Steps []*Container `json:"steps,omitempty"` Steps []*Container `json:"steps,omitempty"`
Trigger Conditions `json:"trigger,omitempty"` Trigger Conditions `json:"trigger,omitempty"`
@ -58,7 +58,7 @@ type (
ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts"` ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts"`
Failure string `json:"failure,omitempty"` Failure string `json:"failure,omitempty"`
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
NetworkMode string `json:"network_mode,omitempty" yaml:"network_mode"` Network string `json:"network_mode,omitempty" yaml:"network_mode"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Ports []*Port `json:"ports,omitempty"` Ports []*Port `json:"ports,omitempty"`
Privileged bool `json:"privileged,omitempty"` Privileged bool `json:"privileged,omitempty"`
@ -103,22 +103,22 @@ type (
// Volume that can be mounted by containers. // Volume that can be mounted by containers.
Volume struct { Volume struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Temp *VolumeEmptyDir `json:"temp,omitempty" yaml:"temp"` EmptyDir *VolumeEmptyDir `json:"temp,omitempty" yaml:"temp"`
Host *VolumeHostPath `json:"host,omitempty" yaml:"host"` HostPath *VolumeHostPath `json:"host,omitempty" yaml:"host"`
} }
// VolumeDevice describes a mapping of a raw block // VolumeDevice describes a mapping of a raw block
// device within a container. // device within a container.
VolumeDevice struct { VolumeDevice struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Path string `json:"path,omitempty" yaml:"path"` DevicePath string `json:"path,omitempty" yaml:"path"`
} }
// VolumeMount describes a mounting of a Volume // VolumeMount describes a mounting of a Volume
// within a container. // within a container.
VolumeMount struct { VolumeMount struct {
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Path string `json:"path,omitempty" yaml:"path"` MountPath string `json:"path,omitempty" yaml:"path"`
} }
// VolumeEmptyDir mounts a temporary directory from the // VolumeEmptyDir mounts a temporary directory from the
@ -135,7 +135,7 @@ type (
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
} }
// Workspace represents the pipeline workspace configuration. // Workspace represents the pipeline workspace configuraiton.
Workspace struct { Workspace struct {
Base string `json:"base,omitempty"` Base string `json:"base,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`

View File

@ -22,15 +22,12 @@ type (
// UnmarshalYAML implements yaml unmarshalling. // UnmarshalYAML implements yaml unmarshalling.
func (p *Port) UnmarshalYAML(unmarshal func(interface{}) error) error { func (p *Port) UnmarshalYAML(unmarshal func(interface{}) error) error {
out := new(port) out := new(port)
err := unmarshal(&out.Port) err := unmarshal(&out.Port)
if err != nil { if err != nil {
err = unmarshal(&out) err = unmarshal(&out)
} }
p.Port = out.Port p.Port = out.Port
p.Host = out.Host p.Host = out.Host
p.Protocol = out.Protocol p.Protocol = out.Protocol
return err return err
} }

View File

@ -19,7 +19,6 @@ func printContainer(w writer, v *yaml.Container) {
if v.Build != nil { if v.Build != nil {
printBuild(w, v.Build) printBuild(w, v.Build)
} }
if v.Push != nil { if v.Push != nil {
w.WriteTagValue("push", v.Push.Image) w.WriteTagValue("push", v.Push.Image)
} }
@ -33,7 +32,7 @@ func printContainer(w writer, v *yaml.Container) {
w.WriteTagValue("dns", v.DNS) w.WriteTagValue("dns", v.DNS)
w.WriteTagValue("dns_search", v.DNSSearch) w.WriteTagValue("dns_search", v.DNSSearch)
w.WriteTagValue("extra_hosts", v.ExtraHosts) w.WriteTagValue("extra_hosts", v.ExtraHosts)
w.WriteTagValue("network_mode", v.NetworkMode) w.WriteTagValue("network_mode", v.Network)
if len(v.Settings) > 0 { if len(v.Settings) > 0 {
printSettings(w, v.Settings) printSettings(w, v.Settings)
@ -50,28 +49,22 @@ func printContainer(w writer, v *yaml.Container) {
if len(v.Devices) > 0 { if len(v.Devices) > 0 {
printDeviceMounts(w, v.Devices) printDeviceMounts(w, v.Devices)
} }
if len(v.Ports) > 0 { if len(v.Ports) > 0 {
printPorts(w, v.Ports) printPorts(w, v.Ports)
} }
if v.Resources != nil { if v.Resources != nil {
printResources(w, v.Resources) printResources(w, v.Resources)
} }
if len(v.Volumes) > 0 { if len(v.Volumes) > 0 {
printVolumeMounts(w, v.Volumes) printVolumeMounts(w, v.Volumes)
} }
if !isConditionsEmpty(v.When) { if !isConditionsEmpty(v.When) {
printConditions(w, "when", v.When) printConditions(w, "when", v.When)
} }
if len(v.DependsOn) > 0 { if len(v.DependsOn) > 0 {
printDependsOn(w, v.DependsOn) printDependsOn(w, v.DependsOn)
} }
w.WriteByte('\n')
_ = w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }
@ -100,57 +93,50 @@ func printDependsOn(w writer, v []string) {
// helper function pretty prints the device sequence. // helper function pretty prints the device sequence.
func printDeviceMounts(w writer, v []*yaml.VolumeDevice) { func printDeviceMounts(w writer, v []*yaml.VolumeDevice) {
w.WriteTag("devices") w.WriteTag("devices")
for _, v := range v { for _, v := range v {
s := new(indexWriter) s := new(indexWriter)
s.writer = w s.writer = w
s.IndentIncrease() s.IndentIncrease()
s.WriteTagValue("name", v.Name) s.WriteTagValue("name", v.Name)
s.WriteTagValue("path", v.Path) s.WriteTagValue("path", v.DevicePath)
s.IndentDecrease() s.IndentDecrease()
} }
} }
// helper function pretty prints the environment mapping. // helper function pretty prints the environment mapping.
func printEnviron(w writer, v map[string]*yaml.Variable) { func printEnviron(w writer, v map[string]*yaml.Variable) {
keys := make([]string, 0) var keys []string
for k := range v { for k := range v {
keys = append(keys, k) keys = append(keys, k)
} }
sort.Strings(keys) sort.Strings(keys)
w.WriteTag("environment") w.WriteTag("environment")
w.IndentIncrease() w.IndentIncrease()
for _, k := range keys { for _, k := range keys {
v := v[k] v := v[k]
if v.FromSecret == "" { if v.Secret == "" {
w.WriteTagValue(k, v.Value) w.WriteTagValue(k, v.Value)
} else { } else {
w.WriteTag(k) w.WriteTag(k)
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("from_secret", v.FromSecret) w.WriteTagValue("from_secret", v.Secret)
w.IndentDecrease() w.IndentDecrease()
} }
} }
w.IndentDecrease() w.IndentDecrease()
} }
// helper function pretty prints the port sequence. // helper function pretty prints the port sequence.
func printPorts(w writer, v []*yaml.Port) { func printPorts(w writer, v []*yaml.Port) {
w.WriteTag("ports") w.WriteTag("ports")
for _, v := range v { for _, v := range v {
if shortPort(v) { if shortPort(v) {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
_ = w.WriteByte('-') w.WriteByte('-')
_ = w.WriteByte(' ') w.WriteByte(' ')
writeInt(w, v.Port) writeInt(w, v.Port)
continue continue
} }
@ -176,7 +162,6 @@ func printResources(w writer, v *yaml.Resources) {
w.WriteTagValue("memory", v.Limits.Memory) w.WriteTagValue("memory", v.Limits.Memory)
w.IndentDecrease() w.IndentDecrease()
} }
if v.Requests != nil { if v.Requests != nil {
w.WriteTag("requests") w.WriteTag("requests")
w.IndentIncrease() w.IndentIncrease()
@ -184,44 +169,38 @@ func printResources(w writer, v *yaml.Resources) {
w.WriteTagValue("memory", v.Requests.Memory) w.WriteTagValue("memory", v.Requests.Memory)
w.IndentDecrease() w.IndentDecrease()
} }
w.IndentDecrease() w.IndentDecrease()
} }
// helper function pretty prints the resoure mapping. // helper function pretty prints the resoure mapping.
func printSettings(w writer, v map[string]*yaml.Parameter) { func printSettings(w writer, v map[string]*yaml.Parameter) {
keys := make([]string, 0) var keys []string
for k := range v { for k := range v {
keys = append(keys, k) keys = append(keys, k)
} }
sort.Strings(keys) sort.Strings(keys)
w.WriteTag("settings") w.WriteTag("settings")
w.IndentIncrease() w.IndentIncrease()
for _, k := range keys { for _, k := range keys {
v := v[k] v := v[k]
if v.FromSecret == "" { if v.Secret == "" {
w.IncludeZero() w.IncludeZero()
w.WriteTagValue(k, v.Value) w.WriteTagValue(k, v.Value)
w.ExcludeZero() w.ExcludeZero()
} else { } else {
w.WriteTag(k) w.WriteTag(k)
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("from_secret", v.FromSecret) w.WriteTagValue("from_secret", v.Secret)
w.IndentDecrease() w.IndentDecrease()
} }
} }
w.IndentDecrease() w.IndentDecrease()
} }
// helper function pretty prints the volume sequence. // helper function pretty prints the volume sequence.
func printVolumeMounts(w writer, v []*yaml.VolumeMount) { func printVolumeMounts(w writer, v []*yaml.VolumeMount) {
w.WriteTag("volumes") w.WriteTag("volumes")
for _, v := range v { for _, v := range v {
s := new(indexWriter) s := new(indexWriter)
s.writer = w s.writer = w
@ -229,7 +208,7 @@ func printVolumeMounts(w writer, v []*yaml.VolumeMount) {
s.IndentIncrease() s.IndentIncrease()
s.WriteTagValue("name", v.Name) s.WriteTagValue("name", v.Name)
s.WriteTagValue("path", v.Path) s.WriteTagValue("path", v.MountPath)
s.IndentDecrease() s.IndentDecrease()
w.IndentDecrease() w.IndentDecrease()

View File

@ -7,13 +7,13 @@ import "github.com/drone/drone-yaml/yaml"
// helper function pretty prints the cron resource. // helper function pretty prints the cron resource.
func printCron(w writer, v *yaml.Cron) { func printCron(w writer, v *yaml.Cron) {
_, _ = w.WriteString("---") w.WriteString("---")
w.WriteTagValue("version", v.Version) w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind) w.WriteTagValue("kind", v.Kind)
w.WriteTagValue("name", v.Name) w.WriteTagValue("name", v.Name)
printSpec(w, v) printSpec(w, v)
_ = w.WriteByte('\n') w.WriteByte('\n')
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
// helper function pretty prints the spec block. // helper function pretty prints the spec block.
@ -23,11 +23,9 @@ func printSpec(w writer, v *yaml.Cron) {
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("schedule", v.Spec.Schedule) w.WriteTagValue("schedule", v.Spec.Schedule)
w.WriteTagValue("branch", v.Spec.Branch) w.WriteTagValue("branch", v.Spec.Branch)
if hasDeployment(v) { if hasDeployment(v) {
printDeploy(w, v) printDeploy(w, v)
} }
w.IndentDecrease() w.IndentDecrease()
} }
@ -35,12 +33,12 @@ func printSpec(w writer, v *yaml.Cron) {
func printDeploy(w writer, v *yaml.Cron) { func printDeploy(w writer, v *yaml.Cron) {
w.WriteTag("deployment") w.WriteTag("deployment")
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("target", v.Spec.Deployment.Target) w.WriteTagValue("target", v.Spec.Deploy.Target)
w.IndentDecrease() w.IndentDecrease()
} }
// helper function returns true if the deployment // helper function returns true if the deployment
// object is empty. // object is empty.
func hasDeployment(v *yaml.Cron) bool { func hasDeployment(v *yaml.Cron) bool {
return v.Spec.Deployment.Target != "" return v.Spec.Deploy.Target != ""
} }

View File

@ -9,39 +9,34 @@ import (
// helper function to pretty print the pipeline resource. // helper function to pretty print the pipeline resource.
func printPipeline(w writer, v *yaml.Pipeline) { func printPipeline(w writer, v *yaml.Pipeline) {
_, _ = w.WriteString("---") w.WriteString("---")
w.WriteTagValue("version", v.Version) w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind) w.WriteTagValue("kind", v.Kind)
w.WriteTagValue("type", v.Type) w.WriteTagValue("type", v.Type)
w.WriteTagValue("name", v.Name) w.WriteTagValue("name", v.Name)
_ = w.WriteByte('\n') w.WriteByte('\n')
if !isPlatformEmpty(v.Platform) { if !isPlatformEmpty(v.Platform) {
printPlatform(w, v.Platform) printPlatform(w, v.Platform)
} else { } else {
printPlatformDefault(w) printPlatformDefault(w)
} }
if !isCloneEmpty(v.Clone) { if !isCloneEmpty(v.Clone) {
printClone(w, v.Clone) printClone(w, v.Clone)
} }
if !isConcurrencyEmpty(v.Concurrency) { if !isConcurrencyEmpty(v.Concurrency) {
printConcurrency(w, v.Concurrency) printConcurrency(w, v.Concurrency)
} }
if !isWorkspaceEmpty(v.Workspace) { if !isWorkspaceEmpty(v.Workspace) {
printWorkspace(w, v.Workspace) printWorkspace(w, v.Workspace)
} }
if len(v.Steps) > 0 { if len(v.Steps) > 0 {
w.WriteTag("steps") w.WriteTag("steps")
for _, step := range v.Steps { for _, step := range v.Steps {
if step == nil { if step == nil {
continue continue
} }
seq := new(indexWriter) seq := new(indexWriter)
seq.writer = w seq.writer = w
seq.IndentIncrease() seq.IndentIncrease()
@ -52,12 +47,10 @@ func printPipeline(w writer, v *yaml.Pipeline) {
if len(v.Services) > 0 { if len(v.Services) > 0 {
w.WriteTag("services") w.WriteTag("services")
for _, step := range v.Services { for _, step := range v.Services {
if step == nil { if step == nil {
continue continue
} }
seq := new(indexWriter) seq := new(indexWriter)
seq.writer = w seq.writer = w
seq.IndentIncrease() seq.IndentIncrease()
@ -68,30 +61,30 @@ func printPipeline(w writer, v *yaml.Pipeline) {
if len(v.Volumes) != 0 { if len(v.Volumes) != 0 {
printVolumes(w, v.Volumes) printVolumes(w, v.Volumes)
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
if len(v.ImagePullSecrets) > 0 { if len(v.PullSecrets) > 0 {
w.WriteTagValue("image_pull_secrets", v.ImagePullSecrets) w.WriteTagValue("image_pull_secrets", v.PullSecrets)
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
if len(v.Node) > 0 { if len(v.Node) > 0 {
printNode(w, v.Node) printNode(w, v.Node)
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
if !isConditionsEmpty(v.Trigger) { if !isConditionsEmpty(v.Trigger) {
printConditions(w, "trigger", v.Trigger) printConditions(w, "trigger", v.Trigger)
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
if len(v.DependsOn) > 0 { if len(v.DependsOn) > 0 {
printDependsOn(w, v.DependsOn) printDependsOn(w, v.DependsOn)
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
_ = w.WriteByte('\n') w.WriteByte('\n')
} }
// helper function pretty prints the clone block. // helper function pretty prints the clone block.
@ -101,7 +94,7 @@ func printClone(w writer, v yaml.Clone) {
w.WriteTagValue("depth", v.Depth) w.WriteTagValue("depth", v.Depth)
w.WriteTagValue("disable", v.Disable) w.WriteTagValue("disable", v.Disable)
w.WriteTagValue("skip_verify", v.SkipVerify) w.WriteTagValue("skip_verify", v.SkipVerify)
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }
@ -110,7 +103,7 @@ func printConcurrency(w writer, v yaml.Concurrency) {
w.WriteTag("concurrency") w.WriteTag("concurrency")
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("limit", v.Limit) w.WriteTagValue("limit", v.Limit)
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }
@ -118,68 +111,54 @@ func printConcurrency(w writer, v yaml.Concurrency) {
func printConditions(w writer, name string, v yaml.Conditions) { func printConditions(w writer, name string, v yaml.Conditions) {
w.WriteTag(name) w.WriteTag(name)
w.IndentIncrease() w.IndentIncrease()
if !isConditionEmpty(v.Action) { if !isConditionEmpty(v.Action) {
printCondition(w, "action", v.Action) printCondition(w, "action", v.Action)
} }
if !isConditionEmpty(v.Branch) { if !isConditionEmpty(v.Branch) {
printCondition(w, "branch", v.Branch) printCondition(w, "branch", v.Branch)
} }
if !isConditionEmpty(v.Cron) { if !isConditionEmpty(v.Cron) {
printCondition(w, "cron", v.Cron) printCondition(w, "cron", v.Cron)
} }
if !isConditionEmpty(v.Event) { if !isConditionEmpty(v.Event) {
printCondition(w, "event", v.Event) printCondition(w, "event", v.Event)
} }
if !isConditionEmpty(v.Instance) { if !isConditionEmpty(v.Instance) {
printCondition(w, "instance", v.Instance) printCondition(w, "instance", v.Instance)
} }
if !isConditionEmpty(v.Paths) { if !isConditionEmpty(v.Paths) {
printCondition(w, "paths", v.Paths) printCondition(w, "paths", v.Paths)
} }
if !isConditionEmpty(v.Ref) { if !isConditionEmpty(v.Ref) {
printCondition(w, "ref", v.Ref) printCondition(w, "ref", v.Ref)
} }
if !isConditionEmpty(v.Repo) { if !isConditionEmpty(v.Repo) {
printCondition(w, "repo", v.Repo) printCondition(w, "repo", v.Repo)
} }
if !isConditionEmpty(v.Status) { if !isConditionEmpty(v.Status) {
printCondition(w, "status", v.Status) printCondition(w, "status", v.Status)
} }
if !isConditionEmpty(v.Target) { if !isConditionEmpty(v.Target) {
printCondition(w, "target", v.Target) printCondition(w, "target", v.Target)
} }
w.IndentDecrease() w.IndentDecrease()
} }
// helper function pretty prints a condition mapping. // helper function pretty prints a condition mapping.
func printCondition(w writer, k string, v yaml.Condition) { func printCondition(w writer, k string, v yaml.Condition) {
w.WriteTag(k) w.WriteTag(k)
if len(v.Include) != 0 && len(v.Exclude) == 0 { if len(v.Include) != 0 && len(v.Exclude) == 0 {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentIncrease() w.IndentIncrease()
w.Indent() w.Indent()
writeValue(w, v.Include) writeValue(w, v.Include)
w.IndentDecrease() w.IndentDecrease()
} }
if len(v.Include) != 0 && len(v.Exclude) != 0 { if len(v.Include) != 0 && len(v.Exclude) != 0 {
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("include", v.Include) w.WriteTagValue("include", v.Include)
w.IndentDecrease() w.IndentDecrease()
} }
if len(v.Exclude) != 0 { if len(v.Exclude) != 0 {
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("exclude", v.Exclude) w.WriteTagValue("exclude", v.Exclude)
@ -200,7 +179,7 @@ func printPlatform(w writer, v yaml.Platform) {
w.WriteTagValue("arch", v.Arch) w.WriteTagValue("arch", v.Arch)
w.WriteTagValue("variant", v.Variant) w.WriteTagValue("variant", v.Variant)
w.WriteTagValue("version", v.Version) w.WriteTagValue("version", v.Version)
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }
@ -211,14 +190,13 @@ func printPlatformDefault(w writer) {
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("os", "linux") w.WriteTagValue("os", "linux")
w.WriteTagValue("arch", "amd64") w.WriteTagValue("arch", "amd64")
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }
// helper function pretty prints the volume sequence. // helper function pretty prints the volume sequence.
func printVolumes(w writer, v []*yaml.Volume) { func printVolumes(w writer, v []*yaml.Volume) {
w.WriteTag("volumes") w.WriteTag("volumes")
for _, v := range v { for _, v := range v {
s := new(indexWriter) s := new(indexWriter)
s.writer = w s.writer = w
@ -226,14 +204,12 @@ func printVolumes(w writer, v []*yaml.Volume) {
s.IndentIncrease() s.IndentIncrease()
s.WriteTagValue("name", v.Name) s.WriteTagValue("name", v.Name)
if v := v.EmptyDir; v != nil {
if v := v.Temp; v != nil {
s.WriteTag("temp") s.WriteTag("temp")
if isEmptyDirEmpty(v) { if isEmptyDirEmpty(v) {
_ = w.WriteByte(' ') w.WriteByte(' ')
_ = w.WriteByte('{') w.WriteByte('{')
_ = w.WriteByte('}') w.WriteByte('}')
} else { } else {
s.IndentIncrease() s.IndentIncrease()
s.WriteTagValue("medium", v.Medium) s.WriteTagValue("medium", v.Medium)
@ -242,7 +218,7 @@ func printVolumes(w writer, v []*yaml.Volume) {
} }
} }
if v := v.Host; v != nil { if v := v.HostPath; v != nil {
s.WriteTag("host") s.WriteTag("host")
s.IndentIncrease() s.IndentIncrease()
s.WriteTagValue("path", v.Path) s.WriteTagValue("path", v.Path)
@ -260,7 +236,7 @@ func printWorkspace(w writer, v yaml.Workspace) {
w.IndentIncrease() w.IndentIncrease()
w.WriteTagValue("base", v.Base) w.WriteTagValue("base", v.Base)
w.WriteTagValue("path", v.Path) w.WriteTagValue("path", v.Path)
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentDecrease() w.IndentDecrease()
} }

View File

@ -12,7 +12,6 @@ import (
// Print pretty prints the manifest. // Print pretty prints the manifest.
func Print(w io.Writer, v *yaml.Manifest) { func Print(w io.Writer, v *yaml.Manifest) {
state := new(baseWriter) state := new(baseWriter)
for _, r := range v.Resources { for _, r := range v.Resources {
switch t := r.(type) { switch t := r.(type) {
case *yaml.Cron: case *yaml.Cron:
@ -25,8 +24,7 @@ func Print(w io.Writer, v *yaml.Manifest) {
printPipeline(state, t) printPipeline(state, t)
} }
} }
state.WriteString("...") state.WriteString("...")
state.WriteByte('\n') state.WriteByte('\n')
_, _ = w.Write(state.Bytes()) w.Write(state.Bytes())
} }

View File

@ -9,9 +9,11 @@ import (
"github.com/drone/drone-yaml/yaml" "github.com/drone/drone-yaml/yaml"
) )
// TODO consider "!!binary |" for secret value
// helper function to pretty prints the signature resource. // helper function to pretty prints the signature resource.
func printSecret(w writer, v *yaml.Secret) { func printSecret(w writer, v *yaml.Secret) {
_, _ = w.WriteString("---") w.WriteString("---")
w.WriteTagValue("version", v.Version) w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind) w.WriteTagValue("kind", v.Kind)
w.WriteTagValue("type", v.Type) w.WriteTagValue("type", v.Type)
@ -20,15 +22,13 @@ func printSecret(w writer, v *yaml.Secret) {
w.WriteTagValue("name", v.Name) w.WriteTagValue("name", v.Name)
printData(w, v.Data) printData(w, v.Data)
} }
if !isSecretGetEmpty(v.Get) { if !isSecretGetEmpty(v.Get) {
w.WriteTagValue("name", v.Name) w.WriteTagValue("name", v.Name)
_ = w.WriteByte('\n') w.WriteByte('\n')
printGet(w, v.Get) printGet(w, v.Get)
} }
w.WriteByte('\n')
_ = w.WriteByte('\n') w.WriteByte('\n')
_ = w.WriteByte('\n')
} }
// helper function prints the get block. // helper function prints the get block.
@ -42,24 +42,22 @@ func printGet(w writer, v yaml.SecretGet) {
} }
func printData(w writer, d string) { func printData(w writer, d string) {
spaceReplacer := strings.NewReplacer(" ", "", "\n", "")
w.WriteTag("data") w.WriteTag("data")
_ = w.WriteByte(' ') w.WriteByte(' ')
_ = w.WriteByte('>') w.WriteByte('>')
w.IndentIncrease() w.IndentIncrease()
d = spaceReplacer.Replace(d) d = spaceReplacer.Replace(d)
//nolint:gomnd
for _, s := range chunk(d, 60) { for _, s := range chunk(d, 60) {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
_, _ = w.WriteString(s) w.WriteString(s)
} }
w.IndentDecrease() w.IndentDecrease()
} }
// replace spaces and newlines.
var spaceReplacer = strings.NewReplacer(" ", "", "\n", "")
// helper function returns true if the secret get // helper function returns true if the secret get
// object is empty. // object is empty.
func isSecretGetEmpty(v yaml.SecretGet) bool { func isSecretGetEmpty(v yaml.SecretGet) bool {

View File

@ -9,10 +9,10 @@ import (
// helper function pretty prints the signature resource. // helper function pretty prints the signature resource.
func printSignature(w writer, v *yaml.Signature) { func printSignature(w writer, v *yaml.Signature) {
_, _ = w.WriteString("---") w.WriteString("---")
w.WriteTagValue("version", v.Version) w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind) w.WriteTagValue("kind", v.Kind)
w.WriteTagValue("hmac", v.Hmac) w.WriteTagValue("hmac", v.Hmac)
_ = w.WriteByte('\n') w.WriteByte('\n')
_ = w.WriteByte('\n') w.WriteByte('\n')
} }

View File

@ -72,7 +72,6 @@ func isQuoted(s string) bool {
} }
var r0, r1 byte var r0, r1 byte
t := strings.TrimSpace(s) t := strings.TrimSpace(s)
// if the trimmed string does not match the string, it // if the trimmed string does not match the string, it
@ -85,7 +84,6 @@ func isQuoted(s string) bool {
if len(t) > 0 { if len(t) > 0 {
r0 = t[0] r0 = t[0]
} }
if len(t) > 1 { if len(t) > 1 {
r1 = t[1] r1 = t[1]
} }
@ -105,7 +103,6 @@ func isQuoted(s string) bool {
} }
var prev rune var prev rune
for _, b := range s { for _, b := range s {
switch { switch {
case isEscapeCode(b): case isEscapeCode(b):
@ -115,7 +112,6 @@ func isQuoted(s string) bool {
case b == '#' && prev == ' ': case b == '#' && prev == ' ':
return true return true
} }
prev = b prev = b
} }
@ -128,17 +124,13 @@ func chunk(s string, chunkSize int) []string {
if len(s) == 0 { if len(s) == 0 {
return []string{s} return []string{s}
} }
var chunks []string var chunks []string
for i := 0; i < len(s); i += chunkSize { for i := 0; i < len(s); i += chunkSize {
nn := i + chunkSize nn := i + chunkSize
if nn > len(s) { if nn > len(s) {
nn = len(s) nn = len(s)
} }
chunks = append(chunks, s[i:nn]) chunks = append(chunks, s[i:nn])
} }
return chunks return chunks
} }

View File

@ -71,7 +71,6 @@ func TestQuoted(t *testing.T) {
writeEncode(buf, test.before) writeEncode(buf, test.before)
a := test.after a := test.after
b := buf.String() b := buf.String()
if b != a { if b != a {
t.Errorf("Want %q, got %q", a, b) t.Errorf("Want %q, got %q", a, b)
} }
@ -79,17 +78,16 @@ func TestQuoted(t *testing.T) {
} }
func TestChunk(t *testing.T) { func TestChunk(t *testing.T) {
testChunk := []string{
"ZDllMjFjZDg3Zjk0ZWFjZDRhMjdhMTA1ZDQ1OTVkYTA1ODBjMTk0ZWVlZjQyNmU4",
"N2RiNTIwZjg0NWQwYjcyYjE3MmFmZDIyYzg3NTQ1N2YyYzgxODhjYjJmNDhhOTFj",
"ZjdhMzA0YjEzYWFlMmYxMTIwMmEyM2Q1YjQ5Yjg2ZmMK",
}
s := strings.Join(testChunk, "") s := strings.Join(testChunk, "")
got, want := chunk(s, 64), testChunk got, want := chunk(s, 64), testChunk
if diff := cmp.Diff(got, want); diff != "" { if diff := cmp.Diff(got, want); diff != "" {
t.Errorf("Unexpected chunk value") t.Errorf("Unexpected chunk value")
t.Log(diff) t.Log(diff)
} }
} }
var testChunk = []string{
"ZDllMjFjZDg3Zjk0ZWFjZDRhMjdhMTA1ZDQ1OTVkYTA1ODBjMTk0ZWVlZjQyNmU4",
"N2RiNTIwZjg0NWQwYjcyYjE3MmFmZDIyYzg3NTQ1N2YyYzgxODhjYjJmNDhhOTFj",
"ZjdhMzA0YjEzYWFlMmYxMTIwMmEyM2Q1YjQ5Yjg2ZmMK",
}

View File

@ -12,6 +12,9 @@ import (
"github.com/drone/drone-yaml/yaml" "github.com/drone/drone-yaml/yaml"
) )
// TODO rename WriteTag to WriteKey
// TODO rename WriteTagValue to WriteKeyValue
// ESCAPING: // ESCAPING:
// //
// The string starts with a special character: // The string starts with a special character:
@ -68,7 +71,7 @@ type baseWriter struct {
func (w *baseWriter) Indent() { func (w *baseWriter) Indent() {
for i := 0; i < w.depth; i++ { for i := 0; i < w.depth; i++ {
_, _ = w.WriteString(" ") w.WriteString(" ")
} }
} }
@ -89,32 +92,29 @@ func (w *baseWriter) ExcludeZero() {
} }
func (w *baseWriter) WriteTag(v interface{}) { func (w *baseWriter) WriteTag(v interface{}) {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
_ = w.WriteByte(':') w.WriteByte(':')
} }
func (w *baseWriter) WriteTagValue(k, v interface{}) { func (w *baseWriter) WriteTagValue(k, v interface{}) {
if isZero(v) && !w.zero { if isZero(v) && !w.zero {
return return
} }
w.WriteTag(k) w.WriteTag(k)
if isPrimative(v) {
switch { w.WriteByte(' ')
case isPrimative(v):
_ = w.WriteByte(' ')
writeValue(w, v) writeValue(w, v)
case isSlice(v): } else if isSlice(v) {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentIncrease() w.IndentIncrease()
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
w.IndentDecrease() w.IndentDecrease()
default: } else {
w.depth++ w.depth++
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
w.depth-- w.depth--
@ -140,20 +140,18 @@ func (w *indexWriter) ExcludeZero() {
} }
func (w *indexWriter) WriteTag(v interface{}) { func (w *indexWriter) WriteTag(v interface{}) {
_ = w.WriteByte('\n') w.WriteByte('\n')
if w.index == 0 { if w.index == 0 {
w.IndentDecrease() w.IndentDecrease()
w.Indent() w.Indent()
w.IndentIncrease() w.IndentIncrease()
_ = w.WriteByte('-') w.WriteByte('-')
_ = w.WriteByte(' ') w.WriteByte(' ')
} else { } else {
w.Indent() w.Indent()
} }
writeValue(w, v) writeValue(w, v)
_ = w.WriteByte(':') w.WriteByte(':')
w.index++ w.index++
} }
@ -161,22 +159,19 @@ func (w *indexWriter) WriteTagValue(k, v interface{}) {
if isZero(v) && !w.zero { if isZero(v) && !w.zero {
return return
} }
w.WriteTag(k) w.WriteTag(k)
if isPrimative(v) {
switch { w.WriteByte(' ')
case isPrimative(v):
_ = w.WriteByte(' ')
writeValue(w, v) writeValue(w, v)
case isSlice(v): } else if isSlice(v) {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.IndentIncrease() w.IndentIncrease()
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
w.IndentDecrease() w.IndentDecrease()
default: } else {
w.IndentIncrease() w.IndentIncrease()
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
w.IndentDecrease() w.IndentDecrease()
@ -188,51 +183,47 @@ func (w *indexWriter) WriteTagValue(k, v interface{}) {
// //
func writeBool(w writer, v bool) { func writeBool(w writer, v bool) {
_, _ = w.WriteString( w.WriteString(
strconv.FormatBool(v), strconv.FormatBool(v),
) )
} }
func writeFloat(w writer, v float64) { func writeFloat(w writer, v float64) {
_, _ = w.WriteString( w.WriteString(
strconv.FormatFloat(v, 'g', -1, 64), strconv.FormatFloat(v, 'g', -1, 64),
) )
} }
func writeInt(w writer, v int) { func writeInt(w writer, v int) {
_, _ = w.WriteString( w.WriteString(
strconv.Itoa(v), strconv.Itoa(v),
) )
} }
func writeInt64(w writer, v int64) { func writeInt64(w writer, v int64) {
_, _ = w.WriteString( w.WriteString(
strconv.FormatInt(v, 10), strconv.FormatInt(v, 10),
) )
} }
func writeEncode(w writer, v string) { func writeEncode(w writer, v string) {
if len(v) == 0 { if len(v) == 0 {
_ = w.WriteByte('"') w.WriteByte('"')
_ = w.WriteByte('"') w.WriteByte('"')
return return
} }
if isQuoted(v) { if isQuoted(v) {
fmt.Fprintf(w, "%q", v) fmt.Fprintf(w, "%q", v)
} else { } else {
_, _ = w.WriteString(v) w.WriteString(v)
} }
} }
func writeValue(w writer, v interface{}) { func writeValue(w writer, v interface{}) {
if v == nil { if v == nil {
_ = w.WriteByte('~') w.WriteByte('~')
return return
} }
switch v := v.(type) { switch v := v.(type) {
case bool, int, int64, float64, string: case bool, int, int64, float64, string:
writeScalar(w, v) writeScalar(w, v)
@ -266,20 +257,17 @@ func writeScalar(w writer, v interface{}) {
func writeSequence(w writer, v []interface{}) { func writeSequence(w writer, v []interface{}) {
if len(v) == 0 { if len(v) == 0 {
_ = w.WriteByte('[') w.WriteByte('[')
_ = w.WriteByte(']') w.WriteByte(']')
return return
} }
for i, v := range v { for i, v := range v {
if i != 0 { if i != 0 {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
} }
w.WriteByte('-')
_ = w.WriteByte('-') w.WriteByte(' ')
_ = w.WriteByte(' ')
w.IndentIncrease() w.IndentIncrease()
writeValue(w, v) writeValue(w, v)
w.IndentDecrease() w.IndentDecrease()
@ -288,61 +276,50 @@ func writeSequence(w writer, v []interface{}) {
func writeSequenceStr(w writer, v []string) { func writeSequenceStr(w writer, v []string) {
if len(v) == 0 { if len(v) == 0 {
_ = w.WriteByte('[') w.WriteByte('[')
_ = w.WriteByte(']') w.WriteByte(']')
return return
} }
for i, v := range v { for i, v := range v {
if i != 0 { if i != 0 {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
} }
w.WriteByte('-')
_ = w.WriteByte('-') w.WriteByte(' ')
_ = w.WriteByte(' ')
writeEncode(w, v) writeEncode(w, v)
} }
} }
func writeMapping(w writer, v map[interface{}]interface{}) { func writeMapping(w writer, v map[interface{}]interface{}) {
if len(v) == 0 { if len(v) == 0 {
_ = w.WriteByte('{') w.WriteByte('{')
_ = w.WriteByte('}') w.WriteByte('}')
return return
} }
var keys []string
keys := make([]string, 0)
for k := range v { for k := range v {
s := fmt.Sprint(k) s := fmt.Sprint(k)
keys = append(keys, s) keys = append(keys, s)
} }
sort.Strings(keys) sort.Strings(keys)
for i, k := range keys { for i, k := range keys {
v := v[k] v := v[k]
if i != 0 { if i != 0 {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
} }
writeEncode(w, k) writeEncode(w, k)
_ = w.WriteByte(':') w.WriteByte(':')
if v == nil || isPrimative(v) || isZero(v) { if v == nil || isPrimative(v) || isZero(v) {
_ = w.WriteByte(' ') w.WriteByte(' ')
writeValue(w, v) writeValue(w, v)
} else { } else {
slice := isSlice(v) slice := isSlice(v)
if !slice { if !slice {
w.IndentIncrease() w.IndentIncrease()
} }
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
writeValue(w, v) writeValue(w, v)
if !slice { if !slice {
@ -354,31 +331,24 @@ func writeMapping(w writer, v map[interface{}]interface{}) {
func writeMappingStr(w writer, v map[string]string) { func writeMappingStr(w writer, v map[string]string) {
if len(v) == 0 { if len(v) == 0 {
_ = w.WriteByte('{') w.WriteByte('{')
_ = w.WriteByte('}') w.WriteByte('}')
return return
} }
var keys []string
keys := make([]string, 0)
for k := range v { for k := range v {
keys = append(keys, k) keys = append(keys, k)
} }
sort.Strings(keys) sort.Strings(keys)
for i, k := range keys { for i, k := range keys {
v := v[k] v := v[k]
if i != 0 { if i != 0 {
_ = w.WriteByte('\n') w.WriteByte('\n')
w.Indent() w.Indent()
} }
writeEncode(w, k) writeEncode(w, k)
_ = w.WriteByte(':') w.WriteByte(':')
_ = w.WriteByte(' ') w.WriteByte(' ')
writeEncode(w, v) writeEncode(w, v)
} }
} }

View File

@ -13,7 +13,25 @@ import (
// this unit tests pretty prints a complex yaml structure // this unit tests pretty prints a complex yaml structure
// to ensure we have common use cases covered. // to ensure we have common use cases covered.
func TestWriteComplexValue(t *testing.T) { func TestWriteComplexValue(t *testing.T) {
testComplexValue := ` block := map[interface{}]interface{}{}
err := yaml.Unmarshal([]byte(testComplexValue), &block)
if err != nil {
t.Error(err)
return
}
b := new(baseWriter)
writeValue(b, block)
got, want := b.String(), strings.TrimSpace(testComplexValue)
if got != want {
t.Errorf("Unexpected block format")
println(got)
println("---")
println(want)
}
}
var testComplexValue = `
a: b a: b
c: c:
- d - d
@ -39,24 +57,3 @@ x: ~
z: "#y" z: "#y"
zz: "\nz\n" zz: "\nz\n"
"{z}": z` "{z}": z`
block := map[interface{}]interface{}{}
err := yaml.Unmarshal([]byte(testComplexValue), &block)
if err != nil {
t.Error(err)
return
}
b := new(baseWriter)
writeValue(b, block)
got, want := b.String(), strings.TrimSpace(testComplexValue)
if got != want {
t.Errorf("Unexpected block format")
println(got)
println("---")
println(want)
}
}

View File

@ -19,13 +19,10 @@ type (
// UnmarshalYAML implements yaml unmarshalling. // UnmarshalYAML implements yaml unmarshalling.
func (p *Push) UnmarshalYAML(unmarshal func(interface{}) error) error { func (p *Push) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(push) d := new(push)
err := unmarshal(&d.Image) err := unmarshal(&d.Image)
if err != nil { if err != nil {
err = unmarshal(d) err = unmarshal(d)
} }
p.Image = d.Image p.Image = d.Image
return err return err
} }

View File

@ -18,8 +18,6 @@ type (
} }
) )
var ErrInvalidRegistry = errors.New("yaml: invalid registry resource")
// GetVersion returns the resource version. // GetVersion returns the resource version.
func (r *Registry) GetVersion() string { return r.Version } func (r *Registry) GetVersion() string { return r.Version }
@ -29,8 +27,7 @@ func (r *Registry) GetKind() string { return r.Kind }
// Validate returns an error if the registry is invalid. // Validate returns an error if the registry is invalid.
func (r *Registry) Validate() error { func (r *Registry) Validate() error {
if len(r.Data) == 0 { if len(r.Data) == 0 {
return ErrInvalidRegistry return errors.New("yaml: invalid registry resource")
} }
return nil return nil
} }

View File

@ -5,6 +5,9 @@ package yaml
import "errors" import "errors"
// TODO(bradrydzewski) deprecate Secret
// TODO(bradrydzewski) deprecate ExternalData
type ( type (
// Secret is a resource that provides encrypted data // Secret is a resource that provides encrypted data
// and pointers to external data (i.e. from vault). // and pointers to external data (i.e. from vault).
@ -19,7 +22,7 @@ type (
} }
// SecretGet defines a request to get a secret from // SecretGet defines a request to get a secret from
// an external service at the specified path, or with the // an external sevice at the specified path, or with the
// specified name. // specified name.
SecretGet struct { SecretGet struct {
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
@ -35,8 +38,6 @@ type (
} }
) )
var ErrInvalidSecret = errors.New("yaml: invalid secret resource")
// GetVersion returns the resource version. // GetVersion returns the resource version.
func (s *Secret) GetVersion() string { return s.Version } func (s *Secret) GetVersion() string { return s.Version }
@ -46,8 +47,7 @@ func (s *Secret) GetKind() string { return s.Kind }
// Validate returns an error if the secret is invalid. // Validate returns an error if the secret is invalid.
func (s *Secret) Validate() error { func (s *Secret) Validate() error {
if len(s.Data) == 0 && len(s.Get.Path) == 0 && len(s.Get.Name) == 0 { if len(s.Data) == 0 && len(s.Get.Path) == 0 && len(s.Get.Name) == 0 {
return ErrInvalidSecret return errors.New("yaml: invalid secret resource")
} }
return nil return nil
} }

View File

@ -17,8 +17,6 @@ type (
} }
) )
var ErrInvalidSignature = errors.New("yaml: invalid signature due to missing hash")
// GetVersion returns the resource version. // GetVersion returns the resource version.
func (s *Signature) GetVersion() string { return s.Version } func (s *Signature) GetVersion() string { return s.Version }
@ -28,8 +26,7 @@ func (s *Signature) GetKind() string { return s.Kind }
// Validate returns an error if the signature is invalid. // Validate returns an error if the signature is invalid.
func (s Signature) Validate() error { func (s Signature) Validate() error {
if s.Hmac == "" { if s.Hmac == "" {
return ErrInvalidSignature return errors.New("yaml: invalid signature. missing hash")
} }
return nil return nil
} }

View File

@ -17,7 +17,6 @@ func (b *BytesSize) UnmarshalYAML(unmarshal func(interface{}) error) error {
var intType int64 var intType int64
if err := unmarshal(&intType); err == nil { if err := unmarshal(&intType); err == nil {
*b = BytesSize(intType) *b = BytesSize(intType)
return nil return nil
} }
@ -30,7 +29,6 @@ func (b *BytesSize) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err == nil { if err == nil {
*b = BytesSize(intType) *b = BytesSize(intType)
} }
return err return err
} }

View File

@ -21,7 +21,7 @@ func TestBytesSize(t *testing.T) {
text: "1KiB", text: "1KiB",
}, },
{ {
yaml: "100MiB", yaml: "100Mi",
size: 104857600, size: 104857600,
text: "100MiB", text: "100MiB",
}, },
@ -34,18 +34,14 @@ func TestBytesSize(t *testing.T) {
for _, test := range tests { for _, test := range tests {
in := []byte(test.yaml) in := []byte(test.yaml)
out := BytesSize(0) out := BytesSize(0)
err := yaml.Unmarshal(in, &out) err := yaml.Unmarshal(in, &out)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
if got, want := int64(out), test.size; got != want { if got, want := int64(out), test.size; got != want {
t.Errorf("Want byte size %d, got %d", want, got) t.Errorf("Want byte size %d, got %d", want, got)
} }
if got, want := out.String(), test.text; got != want { if got, want := out.String(), test.text; got != want {
t.Errorf("Want byte text %s, got %s", want, got) t.Errorf("Want byte text %s, got %s", want, got)
} }