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/
/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
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

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
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)
[![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)
[![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 [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 You can find the full documentation at [https://drone-plugin-index.geekdocs.de](https://drone-plugin-index.geekdocs.de/tools/drone-yaml).
## 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

View File

@ -27,7 +27,7 @@ export GOARCH=amd64
export CGO_ENABLED=0
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:
@ -38,7 +38,8 @@ docker build --file docker/Dockerfile.amd64 --tag thegeeklab/drone-yaml .
## Usage
{{< hint type=important >}}
{{< hint warning >}}
**Note**\
Be aware that the tool only supports configuration files for the Drone Docker runner!
{{< /hint >}}

View File

@ -1,14 +1,4 @@
FROM --platform=$BUILDPLATFORM golang:1.20@sha256:741d6f9bcab778441efe05c8e4369d4f8ff56c9a635a97d77f55d8b0ec62f907 as build
ARG TARGETOS
ARG TARGETARCH
ADD . /src
WORKDIR /src
RUN make build
FROM alpine:3.18@sha256:7144f7bab3d4c2648d7e59409f15ec52a18006a128c733fcff20d3a4a54ba44a
FROM alpine:3.15@sha256:f22945d45ee2eb4dd463ed5a431d9f04fcd80ca768bb1acf898d91ce51f7bf04
LABEL maintainer="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.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" ]

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
go 1.20
go 1.18
require (
github.com/alecthomas/kingpin/v2 v2.3.2
github.com/bmatcuk/doublestar/v4 v4.6.0
github.com/docker/go-units v0.5.0
github.com/google/go-cmp v0.5.9
github.com/bmatcuk/doublestar/v4 v4.0.2
github.com/docker/go-units v0.4.0
github.com/google/go-cmp v0.5.7
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.4.0
honnef.co/go/tools v0.3.0
)
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/davecgh/go-spew v1.1.1 // 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
)

52
go.sum
View File

@ -1,15 +1,18 @@
github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU=
github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
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/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/bmatcuk/doublestar/v4 v4.6.0 h1:HTuxyug8GyFbRkrffIpzNCSK4luc0TY3wzXvzIZhEXc=
github.com/bmatcuk/doublestar/v4 v4.6.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA=
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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.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 (
"bytes"
"io"
"io/ioutil"
"os"
"github.com/alecthomas/kingpin/v2"
"github.com/drone/drone-yaml/yaml"
"github.com/drone/drone-yaml/yaml/linter"
"github.com/drone/drone-yaml/yaml/pretty"
"gopkg.in/alecthomas/kingpin.v2"
)
//nolint:gochecknoglobals
var (
format = kingpin.Command("fmt", "format the yaml file")
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()
)
const DefaultFilePerm = 0o640
func main() {
switch kingpin.Parse() {
case format.FullCommand():
@ -38,7 +37,6 @@ func main() {
func runFormat() error {
f := *formatFile
m, err := yaml.Parse(f)
if err != nil {
return err
@ -48,28 +46,23 @@ func runFormat() error {
pretty.Print(b, m)
if *formatSave {
return os.WriteFile(f.Name(), b.Bytes(), DefaultFilePerm)
return ioutil.WriteFile(f.Name(), b.Bytes(), 0644)
}
_, err = io.Copy(os.Stderr, b)
return err
}
func runLint() error {
f := *lintFile
m, err := yaml.Parse(f)
if err != nil {
return err
}
for _, r := range m.Resources {
err := linter.Lint(r, *lintPriv)
if err != nil {
return err
}
}
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.
func (b *Build) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(build)
err := unmarshal(&d.Image)
if err != nil {
err = unmarshal(d)
}
b.Args = d.Args
b.CacheFrom = d.CacheFrom
b.Context = d.Context
b.Dockerfile = d.Dockerfile
b.Labels = d.Labels
b.Image = d.Image
return err
}

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ import (
var ErrDuplicatePipelineName = errors.New("linter: duplicate pipeline names")
// 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")
// 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")
// Manifest performs lint operations for a manifest.
func Manifest(manifest *yaml.Manifest) error {
return checkPipelines(manifest)
func Manifest(manifest *yaml.Manifest, trusted bool) error {
return checkPipelines(manifest, trusted)
}
func checkPipelines(manifest *yaml.Manifest) error {
func checkPipelines(manifest *yaml.Manifest, trusted bool) error {
names := map[string]struct{}{}
for _, resource := range manifest.Resources {
switch v := resource.(type) {
case *yaml.Pipeline:
@ -41,25 +40,19 @@ func checkPipelines(manifest *yaml.Manifest) error {
if ok {
return ErrDuplicatePipelineName
}
names[v.Name] = struct{}{}
err := checkPipelineDeps(v, names)
if err != nil {
return err
}
if (v.Kind == "pipeline" || v.Kind == "") && (v.Type == "" || v.Type == "docker") {
err = checkPlatform(v.Platform)
if err != nil {
return err
}
}
default:
continue
}
}
return nil
}
@ -69,11 +62,9 @@ func checkPipelineDeps(pipeline *yaml.Pipeline, deps map[string]struct{}) error
if !ok {
return ErrMissingPipelineDependency
}
if pipeline.Name == dep {
return ErrPipelineSelfDependency
}
}
return nil
}

View File

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

View File

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

View File

@ -9,13 +9,13 @@ type (
// to a secret.
Parameter struct {
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
// parameters with references to secrets.
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 {
d := new(parameter)
err := unmarshal(d)
if err == nil && d.FromSecret != "" {
p.FromSecret = d.FromSecret
if err == nil && d.Secret != "" {
p.Secret = d.Secret
return nil
}
var i interface{}
err = unmarshal(&i)
p.Value = i
return err
}
// MarshalYAML implements yaml marshalling.
func (p *Parameter) MarshalYAML() (interface{}, error) {
if p.FromSecret != "" {
if p.Secret != "" {
m := map[string]interface{}{}
m["from_secret"] = p.FromSecret
m["from_secret"] = p.Secret
return m, nil
}
if p.Value != "" {
return p.Value, nil
}
//nolint:nilnil
return nil, nil
}

View File

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

View File

@ -16,7 +16,7 @@ type Pipeline struct {
DependsOn []string `json:"depends_on,omitempty" yaml:"depends_on" `
Node map[string]string `json:"node,omitempty" yaml:"node"`
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"`
Steps []*Container `json:"steps,omitempty"`
Trigger Conditions `json:"trigger,omitempty"`
@ -58,7 +58,7 @@ type (
ExtraHosts []string `json:"extra_hosts,omitempty" yaml:"extra_hosts"`
Failure string `json:"failure,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"`
Ports []*Port `json:"ports,omitempty"`
Privileged bool `json:"privileged,omitempty"`
@ -103,22 +103,22 @@ type (
// Volume that can be mounted by containers.
Volume struct {
Name string `json:"name,omitempty"`
Temp *VolumeEmptyDir `json:"temp,omitempty" yaml:"temp"`
Host *VolumeHostPath `json:"host,omitempty" yaml:"host"`
EmptyDir *VolumeEmptyDir `json:"temp,omitempty" yaml:"temp"`
HostPath *VolumeHostPath `json:"host,omitempty" yaml:"host"`
}
// VolumeDevice describes a mapping of a raw block
// device within a container.
VolumeDevice struct {
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
// within a container.
VolumeMount struct {
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
@ -135,7 +135,7 @@ type (
Path string `json:"path,omitempty"`
}
// Workspace represents the pipeline workspace configuration.
// Workspace represents the pipeline workspace configuraiton.
Workspace struct {
Base string `json:"base,omitempty"`
Path string `json:"path,omitempty"`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,10 +9,10 @@ import (
// helper function pretty prints the signature resource.
func printSignature(w writer, v *yaml.Signature) {
_, _ = w.WriteString("---")
w.WriteString("---")
w.WriteTagValue("version", v.Version)
w.WriteTagValue("kind", v.Kind)
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
t := strings.TrimSpace(s)
// if the trimmed string does not match the string, it
@ -85,7 +84,6 @@ func isQuoted(s string) bool {
if len(t) > 0 {
r0 = t[0]
}
if len(t) > 1 {
r1 = t[1]
}
@ -105,7 +103,6 @@ func isQuoted(s string) bool {
}
var prev rune
for _, b := range s {
switch {
case isEscapeCode(b):
@ -115,7 +112,6 @@ func isQuoted(s string) bool {
case b == '#' && prev == ' ':
return true
}
prev = b
}
@ -128,17 +124,13 @@ func chunk(s string, chunkSize int) []string {
if len(s) == 0 {
return []string{s}
}
var chunks []string
for i := 0; i < len(s); i += chunkSize {
nn := i + chunkSize
if nn > len(s) {
nn = len(s)
}
chunks = append(chunks, s[i:nn])
}
return chunks
}

View File

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

View File

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

View File

@ -13,7 +13,25 @@ import (
// this unit tests pretty prints a complex yaml structure
// to ensure we have common use cases covered.
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
c:
- d
@ -39,24 +57,3 @@ x: ~
z: "#y"
zz: "\nz\n"
"{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.
func (p *Push) UnmarshalYAML(unmarshal func(interface{}) error) error {
d := new(push)
err := unmarshal(&d.Image)
if err != nil {
err = unmarshal(d)
}
p.Image = d.Image
return err
}

View File

@ -18,8 +18,6 @@ type (
}
)
var ErrInvalidRegistry = errors.New("yaml: invalid registry resource")
// GetVersion returns the resource 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.
func (r *Registry) Validate() error {
if len(r.Data) == 0 {
return ErrInvalidRegistry
return errors.New("yaml: invalid registry resource")
}
return nil
}

View File

@ -5,6 +5,9 @@ package yaml
import "errors"
// TODO(bradrydzewski) deprecate Secret
// TODO(bradrydzewski) deprecate ExternalData
type (
// Secret is a resource that provides encrypted data
// and pointers to external data (i.e. from vault).
@ -19,7 +22,7 @@ type (
}
// 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.
SecretGet struct {
Path string `json:"path,omitempty"`
@ -35,8 +38,6 @@ type (
}
)
var ErrInvalidSecret = errors.New("yaml: invalid secret resource")
// GetVersion returns the resource 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.
func (s *Secret) Validate() error {
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
}

View File

@ -17,8 +17,6 @@ type (
}
)
var ErrInvalidSignature = errors.New("yaml: invalid signature due to missing hash")
// GetVersion returns the resource 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.
func (s Signature) Validate() error {
if s.Hmac == "" {
return ErrInvalidSignature
return errors.New("yaml: invalid signature. missing hash")
}
return nil
}

View File

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

View File

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