Compare commits

...

28 Commits

Author SHA1 Message Date
7ed6fee298
chore(deps): update davidanson/markdownlint-cli2-action action to v20
All checks were successful
Golang Tests / unittest (stable, ubuntu-latest-amd64) (pull_request) Successful in 6s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (pull_request) Successful in 8s
Lint Markdown files / markdown-lint (pull_request) Successful in 14s
Golang Tests / unittest (stable, ubuntu-latest-arm64) (pull_request) Successful in 33s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (pull_request) Successful in 46s
Golang Tests / unittest (stable, ubuntu-latest-amd64) (push) Successful in 5s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Successful in 8s
Lint Markdown files / markdown-lint (push) Successful in 4s
Golang Tests / unittest (stable, ubuntu-latest-arm64) (push) Successful in 22s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Successful in 30s
2025-06-01 11:43:25 +00:00
9c256a53c4
chore(ci): use DavidAnson/markdownlint-cli2-action@v19.1.0
All checks were successful
Golang Tests / unittest (stable, ubuntu-latest-amd64) (push) Successful in 6s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Successful in 8s
Lint Markdown files / markdown-lint (push) Successful in 4s
Golang Tests / unittest (stable, ubuntu-latest-arm64) (push) Successful in 31s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Successful in 47s
2025-06-01 13:38:28 +02:00
a5423dfe4d
chore(ci): use matrix to run tests on multiple architectures
All checks were successful
Golang Tests / unittest (stable, ubuntu-latest-amd64) (push) Successful in 27s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Successful in 15s
Markdown linter / markdown-lint (push) Successful in 3s
Golang Tests / unittest (stable, ubuntu-latest-arm64) (push) Successful in 1m18s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Successful in 46s
2025-06-01 12:11:41 +02:00
9705b468fa
chore(ci): be golangci-lint compatible
All checks were successful
Golang Tests / unittest (push) Successful in 28s
Markdown linter / markdown-lint (push) Successful in 3s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Successful in 1m49s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Successful in 2m13s
2025-05-31 23:02:00 +02:00
f8a7634e91
chore(ci): add matrix for golangci-lint
Some checks failed
Markdown linter / markdown-lint (push) Successful in 7s
Golang Tests / unittest (push) Successful in 30s
Golang CI lint / golangci (stable, ubuntu-latest-amd64) (push) Failing after 43s
Golang CI lint / golangci (stable, ubuntu-latest-arm64) (push) Failing after 3m24s
2025-05-31 22:57:52 +02:00
96bdc09d14
chore(ci): add golangci-lint
Some checks failed
Golang Tests / unittest (push) Successful in 30s
Markdown linter / markdown-lint (push) Successful in 10s
Golang CI lint / golangci (push) Failing after 3m0s
2025-05-31 22:54:06 +02:00
96447f88b3
chore(ci): update workflow_dispatch for update docker hub description
All checks were successful
Golang Tests / unittest (push) Successful in 32s
Markdown linter / markdown-lint (push) Successful in 14s
2025-05-31 22:05:54 +02:00
8635fd3334
fix(ignore): add dist directory
All checks were successful
Golang Tests / unittest (push) Successful in 20s
Markdown linter / markdown-lint (push) Successful in 10s
2025-05-31 21:41:49 +02:00
a6da12db45
style(vscode): remove project config
All checks were successful
Markdown linter / markdown-lint (push) Successful in 13s
Golang Tests / unittest (push) Successful in 25s
2025-05-31 21:05:39 +02:00
07067b6b47
chore(Makefile): remove unqualified image tag
All checks were successful
Markdown linter / markdown-lint (push) Successful in 8s
Golang Tests / unittest (push) Successful in 34s
2025-05-31 18:11:35 +02:00
b50b9d8f19
style(linter): be compliant with golangci-lint
All checks were successful
Markdown linter / markdown-lint (push) Successful in 12s
Golang Tests / unittest (push) Successful in 29s
2025-05-29 13:44:55 +02:00
445a9b6799
fix(riscv64): add support
All checks were successful
Markdown linter / markdown-lint (push) Successful in 8s
Golang Tests / unittest (push) Successful in 33s
Release / release (push) Successful in 34s
Release / sync-to-hub-docker-io (push) Successful in 57s
2025-05-29 13:14:21 +02:00
cd521a803b
feat(riscv64): add support
All checks were successful
Markdown linter / markdown-lint (push) Successful in 13s
Golang Tests / unittest (push) Successful in 24s
2025-05-29 13:10:28 +02:00
5c7b14e6cb
chore(deps): update git.cryptic.systems/volker.raschek/markdownlint docker tag to v0.45.0
All checks were successful
Markdown linter / markdown-lint (pull_request) Successful in 3s
Golang Tests / unittest (pull_request) Successful in 3m2s
Markdown linter / markdown-lint (push) Successful in 3s
Golang Tests / unittest (push) Successful in 23s
2025-05-28 13:03:44 +00:00
fb3af62fc3
test(service): adapt exptected result of the command attribut
All checks were successful
Markdown linter / markdown-lint (push) Successful in 14s
Golang Tests / unittest (push) Successful in 30s
2025-05-22 09:58:05 +02:00
e30c7c007f
feat: support service.command
Some checks failed
Markdown linter / markdown-lint (push) Successful in 3s
Release / release (push) Successful in 1m24s
Release / sync-to-hub-docker-io (push) Successful in 28s
Golang Tests / unittest (push) Failing after 2m48s
This patch extends dcmerge to support the command attribut of a defined service.
For example:

```yaml
services:
  busybox
    command: [ "/usr/bin/cp", "--recursive", "--force", "/tmp/bar.txt", "/tmp/foo.txt"]
    image: library/busybox:latest
```

The command attribute is interpreted as a whole. This means that individual
arguments are not merged as a comparison, as this would change the meaning of
the command attribute.
2025-05-22 09:49:43 +02:00
973e90986c
style(markdown): adapt configuration
All checks were successful
Markdown linter / markdown-lint (push) Successful in 8s
Golang Tests / unittest (push) Successful in 29s
2025-05-13 17:53:33 +02:00
90a6350a02
fix(drone): remove configuration
All checks were successful
Golang Tests / unittest (push) Successful in 22s
Markdown linter / markdown-lint (push) Successful in 10s
2025-05-08 14:51:15 +02:00
89f4f5b0fa
chore(deps): update actions/setup-go action to v5.5.0
All checks were successful
Golang Tests / unittest (pull_request) Successful in 2m40s
Markdown linter / markdown-lint (pull_request) Successful in 11s
Markdown linter / markdown-lint (push) Successful in 7s
Golang Tests / unittest (push) Successful in 24s
2025-05-08 04:03:00 +00:00
ee1474a506
chore(deps): update docker.io/library/golang docker tag to v1.24.3
All checks were successful
Markdown linter / markdown-lint (pull_request) Successful in 11s
Golang Tests / unittest (pull_request) Successful in 2m28s
Markdown linter / markdown-lint (push) Successful in 8s
Golang Tests / unittest (push) Successful in 31s
2025-05-06 22:03:33 +00:00
1d33b165eb
chore(deps): update goreleaser/goreleaser-action action to v6.3.0
All checks were successful
Golang Tests / unittest (pull_request) Successful in 47s
Markdown linter / markdown-lint (pull_request) Successful in 11s
Golang Tests / unittest (push) Successful in 45s
Markdown linter / markdown-lint (push) Successful in 12s
2025-04-14 19:07:57 +00:00
6fb289da71
docs(README): remove badge of drone.io
All checks were successful
Golang Tests / unittest (push) Successful in 41s
Markdown linter / markdown-lint (push) Successful in 16s
Update Docker Hub Description / update-description-on-hub-docker-io (push) Successful in 16s
2025-04-14 19:51:56 +02:00
ed0b94e4b8
fix(ci): select correct repository on hub.docker.io
Some checks are pending
Golang Tests / unittest (push) Waiting to run
Markdown linter / markdown-lint (push) Waiting to run
Update Docker Hub Description / update-description-on-hub-docker-io (push) Waiting to run
2025-04-14 19:51:23 +02:00
5f06edff04
chore(ci): use '.yaml' extension 2025-04-14 19:51:23 +02:00
5560d13550
feat(ci): sync description on hub.docker.io
Some checks failed
Markdown linter / markdown-lint (push) Waiting to run
Golang Tests / unittest (push) Has been cancelled
Update Docker Hub Description / update-description-on-hub-docker-io (push) Failing after 10s
2025-04-14 19:45:41 +02:00
6387e972e3
chore(ci): add golang tests
All checks were successful
Golang Tests / unittest (push) Successful in 42s
Markdown linter / markdown-lint (push) Successful in 12s
2025-04-14 19:29:09 +02:00
5eec7fc1a5
chore(ci): add markdownlinter
All checks were successful
Markdown linter / markdown-lint (push) Successful in 8s
2025-04-14 19:20:12 +02:00
0688315658
chore(ci): remove suffix
All checks were successful
Release / release (push) Successful in 1m52s
Release / sync-container-image (push) Successful in 48s
2025-04-14 19:17:56 +02:00
22 changed files with 292 additions and 799 deletions

View File

@ -1,727 +0,0 @@
---
kind: pipeline
type: kubernetes
name: linter
clone:
disable: true
platform:
os: linux
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: markdown lint
commands:
- markdownlint *.md
image: git.cryptic.systems/volker.raschek/markdownlint:0.44.0
resources:
limits:
cpu: 150
memory: 150M
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
memory: 150M
when:
status:
- changed
- failure
trigger:
event:
exclude:
- tag
---
kind: pipeline
type: docker
name: unit-test-amd64
clone:
disable: true
platform:
arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: unit-test
commands:
- go test -v ./...
image: docker.io/library/golang:1.24.2
trigger:
event:
exclude:
- tag
---
kind: pipeline
type: docker
name: unit-test-arm64
clone:
disable: true
platform:
arch: arm64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: unit-test
commands:
- go test -v ./...
image: docker.io/library/golang:1.24.2
trigger:
event:
include:
- pull_request
- push
exclude:
- tag
---
kind: pipeline
type: docker
name: dry-run-amd64
clone:
disable: true
depends_on:
- linter
- unit-test-amd64
platform:
os: linux
arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: false
dockerfile: Dockerfile
dry_run: true
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-amd64
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
branch:
exclude:
- master
event:
- pull_request
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: dry-run-arm64-v8
clone:
disable: true
depends_on:
- linter
- unit-test-arm64
platform:
os: linux
arch: arm64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: false
dockerfile: Dockerfile
dry_run: true
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-arm64-v8
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
branch:
exclude:
- master
event:
- pull_request
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: latest-amd64
clone:
disable: true
depends_on:
- linter
- unit-test-amd64
platform:
os: linux
arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: false
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-amd64
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
branch:
- master
event:
- cron
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: latest-arm64-v8
clone:
disable: true
depends_on:
- linter
- unit-test-arm64
platform:
os: linux
arch: arm64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: false
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
tags: latest-arm64-v8
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
branch:
- master
event:
- cron
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: kubernetes
name: latest-manifest
clone:
disable: true
depends_on:
- latest-amd64
- latest-arm64-v8
# docker.io/plugins/manifest only for amd64 architectures available
node_selector:
kubernetes.io/os: linux
kubernetes.io/arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build-manifest
image: docker.io/plugins/manifest:1.4.0
settings:
auto_tag: false
ignore_missing: true
spec: manifest.tmpl
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
memory: 150M
when:
status:
- changed
- failure
trigger:
branch:
- master
event:
- cron
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: kubernetes
name: latest-sync
clone:
disable: true
depends_on:
- latest-manifest
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: latest-sync
commands:
- skopeo sync --all --src=docker --src-creds=$SRC_CRED_USERNAME:$SRC_CRED_PASSWORD --dest=docker --dest-creds=$DEST_CRED_USERNAME:$DEST_CRED_PASSWORD git.cryptic.systems/volker.raschek/dcmerge docker.io/volkerraschek
environment:
SRC_CRED_USERNAME:
from_secret: git_cryptic_systems_container_registry_user
SRC_CRED_PASSWORD:
from_secret: git_cryptic_systems_container_registry_password
DEST_CRED_USERNAME:
from_secret: container_image_registry_user
DEST_CRED_PASSWORD:
from_secret: container_image_registry_password
image: quay.io/skopeo/stable:v1.18.0
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
memory: 150M
when:
status:
- changed
- failure
trigger:
branch:
- master
event:
- cron
- push
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: tagged-amd64
clone:
disable: true
platform:
os: linux
arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: true
auto_tag_suffix: amd64
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
build_args:
- VERSION=${DRONE_TAG}
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
event:
- tag
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: docker
name: tagged-arm64-v8
clone:
disable: true
platform:
os: linux
arch: arm64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build
image: docker.io/plugins/docker:20.18.8
settings:
auto_tag: true
auto_tag_suffix: arm64-v8
dockerfile: Dockerfile
force_tag: true
no_cache: true
purge: true
mirror:
from_secret: docker_io_mirror
registry: git.cryptic.systems
repo: git.cryptic.systems/volker.raschek/dcmerge
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
build_args:
- VERSION=${DRONE_TAG}
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
when:
status:
- changed
- failure
trigger:
event:
- tag
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: kubernetes
name: tagged-manifest
clone:
disable: true
depends_on:
- tagged-amd64
- tagged-arm64-v8
# docker.io/plugins/manifest only for amd64 architectures available
node_selector:
kubernetes.io/os: linux
kubernetes.io/arch: amd64
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: build-manifest
image: docker.io/plugins/manifest:1.4.0
settings:
auto_tag: true
ignore_missing: true
spec: manifest.tmpl
username:
from_secret: git_cryptic_systems_container_registry_user
password:
from_secret: git_cryptic_systems_container_registry_password
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
memory: 150M
when:
status:
- changed
- failure
trigger:
event:
- tag
repo:
- volker.raschek/dcmerge
---
kind: pipeline
type: kubernetes
name: tagged-sync
clone:
disable: true
depends_on:
- tagged-manifest
steps:
- name: clone
image: git.cryptic.systems/volker.raschek/git:1.4.0
- name: tagged-sync
commands:
- skopeo sync --all --src=docker --src-creds=$SRC_CRED_USERNAME:$SRC_CRED_PASSWORD --dest=docker --dest-creds=$DEST_CRED_USERNAME:$DEST_CRED_PASSWORD git.cryptic.systems/volker.raschek/dcmerge docker.io/volkerraschek
environment:
SRC_CRED_USERNAME:
from_secret: git_cryptic_systems_container_registry_user
SRC_CRED_PASSWORD:
from_secret: git_cryptic_systems_container_registry_password
DEST_CRED_USERNAME:
from_secret: container_image_registry_user
DEST_CRED_PASSWORD:
from_secret: container_image_registry_password
image: quay.io/skopeo/stable:v1.18.0
- name: email-notification
environment:
SMTP_FROM_ADDRESS:
from_secret: smtp_from_address
SMTP_FROM_NAME:
from_secret: smtp_from_name
SMTP_HOST:
from_secret: smtp_host
SMTP_USERNAME:
from_secret: smtp_username
SMTP_PASSWORD:
from_secret: smtp_password
image: git.cryptic.systems/volker.raschek/drone-email:0.1.5
resources:
limits:
cpu: 150
memory: 150M
when:
status:
- changed
- failure
trigger:
event:
- tag
repo:
- volker.raschek/dcmerge

View File

@ -0,0 +1,24 @@
name: Golang Tests
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
jobs:
unittest:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go: [ stable ]
os: [ ubuntu-latest-amd64, ubuntu-latest-arm64 ]
steps:
- uses: actions/checkout@v4.2.2
- uses: actions/setup-go@v5.5.0
with:
go-version: ${{ matrix.go }}
- env:
GOPROXY: ${{ vars.GOPROXY }}
run: make test/unit

View File

@ -0,0 +1,27 @@
name: Golang CI lint
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
permissions:
contents: read
jobs:
golangci:
runs-on: ${{ matrix.os }}
strategy:
matrix:
go: [ stable ]
os: [ ubuntu-latest-amd64, ubuntu-latest-arm64 ]
steps:
- uses: actions/checkout@v4.2.2
- uses: actions/setup-go@v5.5.0
with:
go-version: ${{ matrix.go }}
- uses: golangci/golangci-lint-action@v8.0.0
with:
version: v2.1

View File

@ -0,0 +1,18 @@
name: 'Lint Markdown files'
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '*' ]
tags-ignore: [ '*' ]
jobs:
markdown-lint:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- uses: DavidAnson/markdownlint-cli2-action@v20.0.0
with:
globs: '**/*.md'

View File

@ -2,7 +2,7 @@ name: Release
on: on:
push: push:
tags: [ "*" ] tags: [ '**' ]
permissions: permissions:
contents: write contents: write
@ -14,7 +14,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4.2.2 - uses: actions/checkout@v4.2.2
- uses: docker/setup-qemu-action@v3.6.0 - uses: docker/setup-qemu-action@v3.6.0
- uses: actions/setup-go@v5.4.0 - uses: actions/setup-go@v5.5.0
with: with:
go-version: stable go-version: stable
- uses: docker/login-action@v3.4.0 - uses: docker/login-action@v3.4.0
@ -26,13 +26,14 @@ jobs:
GITEA_TOKEN: ${{ secrets.GIT_CRYPTIC_SYSTEMS_PACKAGE_REGISTRY_TOKEN }} GITEA_TOKEN: ${{ secrets.GIT_CRYPTIC_SYSTEMS_PACKAGE_REGISTRY_TOKEN }}
GONOSUMDB: ${{ vars.GONOSUMDB }} GONOSUMDB: ${{ vars.GONOSUMDB }}
GOPROXY: ${{ vars.GOPROXY }} GOPROXY: ${{ vars.GOPROXY }}
uses: goreleaser/goreleaser-action@v6.2.1 uses: goreleaser/goreleaser-action@v6.3.0
with: with:
version: "~> v2" version: "~> v2"
args: release --clean args: release --clean
sync-container-image: sync-to-hub-docker-io:
needs: release needs:
- release
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Copy images to docker.io - name: Copy images to docker.io
@ -47,5 +48,5 @@ jobs:
--dest-username ${{ secrets.DOCKER_IO_USERNAME }} \ --dest-username ${{ secrets.DOCKER_IO_USERNAME }} \
--src-password ${{ secrets.GIT_CRYPTIC_SYSTEMS_PACKAGE_REGISTRY_TOKEN }} \ --src-password ${{ secrets.GIT_CRYPTIC_SYSTEMS_PACKAGE_REGISTRY_TOKEN }} \
--src-username volker.raschek \ --src-username volker.raschek \
docker://git.cryptic.systems/volker.raschek/dcmerge-goreleaser:${TAG} \ docker://git.cryptic.systems/volker.raschek/dcmerge:${TAG} \
docker://docker.io/volkerraschek/dcmerge-goreleaser:${TAG} docker://docker.io/volkerraschek/dcmerge:${TAG}

View File

@ -0,0 +1,20 @@
name: Update Docker Hub Description
on:
push:
branches: [ 'master' ]
paths: [ 'README.md' ]
workflow_dispatch: {}
jobs:
update-description-on-hub-docker-io:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v4.2.2
- uses: peter-evans/dockerhub-description@v4.0.2
with:
username: ${{ secrets.DOCKER_IO_USERNAME }}
password: ${{ secrets.DOCKER_IO_PASSWORD }}
repository: volkerraschek/dcmerge
readme-filepath: README.md

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
dcmerge dcmerge
coverage.txt coverage.txt
dist

View File

@ -30,6 +30,7 @@ builds:
- amd64 - amd64
- arm - arm
- arm64 - arm64
- riscv64
goarm: goarm:
- "6" - "6"
- "7" - "7"
@ -139,6 +140,25 @@ dockers:
skip_push: false skip_push: false
use: buildx use: buildx
- build_flag_templates:
- --label=org.opencontainers.image.created={{ time "2006-01-02T15:04:05Z07:00" }}
- --label=org.opencontainers.image.description={{ .ProjectName }}
- --label=org.opencontainers.image.documentation={{ .ProjectName }}
- --label=org.opencontainers.image.revision={{ .FullCommit }}
- --label=org.opencontainers.image.source={{ .GitURL }}
- --label=org.opencontainers.image.title={{ .ProjectName }}
- --label=org.opencontainers.image.url=https://git.cryptic.systems/volker.raschek/{{ .ProjectName }}
- --label=org.opencontainers.image.version={{ trimprefix .Tag "v" }}
- --platform=linux/riscv64
- --pull
dockerfile: Dockerfile
goarch: riscv64
goos: linux
image_templates:
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-riscv64'
skip_push: false
use: buildx
docker_manifests: docker_manifests:
- name_template: 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}' - name_template: 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}'
image_templates: image_templates:
@ -146,6 +166,7 @@ docker_manifests:
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v6' - 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v6'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v7' - 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm-v7'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm64' - 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-arm64'
- 'git.cryptic.systems/volker.raschek/{{ .ProjectName }}:{{ trimprefix .Tag "v" }}-riscv64'
gitea_urls: gitea_urls:
api: https://git.cryptic.systems/api/v1 api: https://git.cryptic.systems/api/v1

View File

@ -56,8 +56,6 @@ MD013:
tables: false tables: false
# Include headings # Include headings
headings: true headings: true
# Include headings
headers: true
# Strict length checking # Strict length checking
strict: false strict: false
# Stern length checking # Stern length checking
@ -70,11 +68,6 @@ MD022:
# Blank lines below heading # Blank lines below heading
lines_below: 1 lines_below: 1
# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
MD024:
# Only check sibling headings
allow_different_nesting: true
# MD025/single-title/single-h1 - Multiple top-level headings in the same document # MD025/single-title/single-h1 - Multiple top-level headings in the same document
MD025: MD025:
# Heading level # Heading level

View File

@ -1,3 +0,0 @@
{
"rewrap.wrappingColumn": 120,
}

View File

@ -20,17 +20,12 @@ DCMERGE_IMAGE_NAMESPACE?=${DCMERGE_IMAGE_REGISTRY_USER}
DCMERGE_IMAGE_NAME:=${EXECUTABLE} DCMERGE_IMAGE_NAME:=${EXECUTABLE}
DCMERGE_IMAGE_VERSION?=latest DCMERGE_IMAGE_VERSION?=latest
DCMERGE_IMAGE_FULLY_QUALIFIED=${DCMERGE_IMAGE_REGISTRY_NAME}/${DCMERGE_IMAGE_NAMESPACE}/${DCMERGE_IMAGE_NAME}:${DCMERGE_IMAGE_VERSION} DCMERGE_IMAGE_FULLY_QUALIFIED=${DCMERGE_IMAGE_REGISTRY_NAME}/${DCMERGE_IMAGE_NAMESPACE}/${DCMERGE_IMAGE_NAME}:${DCMERGE_IMAGE_VERSION}
DCMERGE_IMAGE_UNQUALIFIED=${DCMERGE_IMAGE_NAMESPACE}/${DCMERGE_IMAGE_NAME}:${DCMERGE_IMAGE_VERSION}
# BIN # BIN
# ============================================================================== # ==============================================================================
dcmerge: dcmerge:
CGO_ENABLED=0 \ CGO_ENABLED=0 \
GOPRIVATE=$(shell go env GOPRIVATE) \
GOPROXY=$(shell go env GOPROXY) \ GOPROXY=$(shell go env GOPROXY) \
GONOPROXY=$(shell go env GONOPROXY) \
GONOSUMDB=$(shell go env GONOSUMDB) \
GOSUMDB=$(shell go env GOSUMDB) \
go build -ldflags "-X 'main.version=${VERSION}'" -o ${@} main.go go build -ldflags "-X 'main.version=${VERSION}'" -o ${@} main.go
# CLEAN # CLEAN
@ -43,15 +38,21 @@ clean:
# ============================================================================== # ==============================================================================
PHONY+=test/unit PHONY+=test/unit
test/unit: test/unit:
go test -v -p 1 -coverprofile=coverage.txt -covermode=count -timeout 1200s ./pkg/... CGO_ENABLED=0 \
GOPROXY=$(shell go env GOPROXY) \
go test -v -p 1 -coverprofile=coverage.txt -covermode=count -timeout 1200s ./pkg/...
PHONY+=test/integration PHONY+=test/integration
test/integration: test/integration:
go test -v -p 1 -count=1 -timeout 1200s ./it/... CGO_ENABLED=0 \
GOPROXY=$(shell go env GOPROXY) \
go test -v -p 1 -count=1 -timeout 1200s ./it/...
PHONY+=test/coverage PHONY+=test/coverage
test/coverage: test/unit test/coverage: test/unit
go tool cover -html=coverage.txt CGO_ENABLED=0 \
GOPROXY=$(shell go env GOPROXY) \
go tool cover -html=coverage.txt
# GOLANGCI-LINT # GOLANGCI-LINT
# ============================================================================== # ==============================================================================
@ -91,14 +92,13 @@ container-image/build:
--no-cache \ --no-cache \
--pull \ --pull \
--tag ${DCMERGE_IMAGE_FULLY_QUALIFIED} \ --tag ${DCMERGE_IMAGE_FULLY_QUALIFIED} \
--tag ${DCMERGE_IMAGE_UNQUALIFIED} \
. .
# DELETE CONTAINER IMAGE # DELETE CONTAINER IMAGE
# ============================================================================== # ==============================================================================
PHONY:=container-image/delete PHONY:=container-image/delete
container-image/delete: container-image/delete:
- ${CONTAINER_RUNTIME} image rm ${DCMERGE_IMAGE_FULLY_QUALIFIED} ${DCMERGE_IMAGE_UNQUALIFIED} - ${CONTAINER_RUNTIME} image rm ${DCMERGE_IMAGE_FULLY_QUALIFIED}
# PUSH CONTAINER IMAGE # PUSH CONTAINER IMAGE
# ============================================================================== # ==============================================================================

View File

@ -1,6 +1,5 @@
# dcmerge # dcmerge
[![Build Status](https://drone.cryptic.systems/api/badges/volker.raschek/dcmerge/status.svg)](https://drone.cryptic.systems/volker.raschek/dcmerge)
[![Docker Pulls](https://img.shields.io/docker/pulls/volkerraschek/dcmerge)](https://hub.docker.com/r/volkerraschek/dcmerge) [![Docker Pulls](https://img.shields.io/docker/pulls/volkerraschek/dcmerge)](https://hub.docker.com/r/volkerraschek/dcmerge)
`dcmerge` is a small program to merge docker-compose files from multiple sources. It is available via RPM and docker. `dcmerge` is a small program to merge docker-compose files from multiple sources. It is available via RPM and docker.

View File

@ -19,16 +19,18 @@ func Execute(version string) error {
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
Args: cobra.MatchAll(cobra.ExactArgs(1)), Args: cobra.MatchAll(cobra.ExactArgs(1)),
Run: func(cmd *cobra.Command, args []string) { RunE: func(cmd *cobra.Command, args []string) error {
switch args[0] { switch args[0] {
case "bash": case "bash":
cmd.Root().GenBashCompletion(os.Stdout) return cmd.Root().GenBashCompletion(os.Stdout)
case "zsh": case "zsh":
cmd.Root().GenZshCompletion(os.Stdout) return cmd.Root().GenZshCompletion(os.Stdout)
case "fish": case "fish":
cmd.Root().GenFishCompletion(os.Stdout, true) return cmd.Root().GenFishCompletion(os.Stdout, true)
case "powershell": case "powershell":
cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
default:
return fmt.Errorf("unknown shell: %v", args[0])
} }
}, },
} }
@ -53,17 +55,17 @@ dcmerge docker-compose.yml https://git.example.local/user/repo/docker-compose.ym
func run(cmd *cobra.Command, args []string) error { func run(cmd *cobra.Command, args []string) error {
mergeExisting, err := cmd.Flags().GetBool("existing-win") mergeExisting, err := cmd.Flags().GetBool("existing-win")
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse flag last-win: %s", err) return fmt.Errorf("failed to parse flag last-win: %s", err)
} }
mergeLastWin, err := cmd.Flags().GetBool("last-win") mergeLastWin, err := cmd.Flags().GetBool("last-win")
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse flag last-win: %s", err) return fmt.Errorf("failed to parse flag last-win: %s", err)
} }
outputFile, err := cmd.Flags().GetString("output-file") outputFile, err := cmd.Flags().GetString("output-file")
if err != nil { if err != nil {
return fmt.Errorf("Failed to parse flag output-file: %s", err) return fmt.Errorf("failed to parse flag output-file: %s", err)
} }
dockerComposeConfig := dockerCompose.NewConfig() dockerComposeConfig := dockerCompose.NewConfig()
@ -76,7 +78,7 @@ func run(cmd *cobra.Command, args []string) error {
for _, config := range dockerComposeConfigs { for _, config := range dockerComposeConfigs {
switch { switch {
case mergeExisting && mergeLastWin: case mergeExisting && mergeLastWin:
return fmt.Errorf("Neither --first-win or --last-win can be specified - not booth.") return fmt.Errorf("neither --first-win or --last-win can be specified - not booth")
case mergeExisting && !mergeLastWin: case mergeExisting && !mergeLastWin:
dockerComposeConfig.MergeExistingWin(config) dockerComposeConfig.MergeExistingWin(config)
case !mergeExisting && mergeLastWin: case !mergeExisting && mergeLastWin:
@ -97,7 +99,7 @@ func run(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() { _ = f.Close() }()
yamlEncoder := yaml.NewEncoder(f) yamlEncoder := yaml.NewEncoder(f)
yamlEncoder.SetIndent(2) yamlEncoder.SetIndent(2)

View File

@ -5,5 +5,5 @@ import "git.cryptic.systems/volker.raschek/dcmerge/cmd"
var version string var version string
func main() { func main() {
cmd.Execute(version) _ = cmd.Execute(version)
} }

View File

@ -1,20 +0,0 @@
image: git.cryptic.systems/volker.raschek/dcmerge:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
- "latest"
{{/if}}
manifests:
-
image: git.cryptic.systems/volker.raschek/dcmerge:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}-amd64
platform:
architecture: amd64
os: linux
-
image: git.cryptic.systems/volker.raschek/dcmerge:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}-arm64-v8
platform:
architecture: arm64
os: linux
variant: v8

View File

@ -531,6 +531,7 @@ func NewSecret() *Secret {
} }
type Service struct { type Service struct {
Command []string `json:"command,omitempty" yaml:"command,omitempty"`
CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"` CapabilitiesAdd []string `json:"cap_add,omitempty" yaml:"cap_add,omitempty"`
CapabilitiesDrop []string `json:"cap_drop,omitempty" yaml:"cap_drop,omitempty"` CapabilitiesDrop []string `json:"cap_drop,omitempty" yaml:"cap_drop,omitempty"`
DependsOnContainer *DependsOnContainer `json:"depends_on,omitempty" yaml:"depends_on,omitempty"` DependsOnContainer *DependsOnContainer `json:"depends_on,omitempty" yaml:"depends_on,omitempty"`
@ -641,7 +642,8 @@ func (s *Service) Equal(equalable Equalable) bool {
case s == nil && service != nil: case s == nil && service != nil:
return false return false
default: default:
return equalSlice(s.CapabilitiesAdd, service.CapabilitiesAdd) && return equalSlice(s.Command, service.Command) &&
equalSlice(s.CapabilitiesAdd, service.CapabilitiesAdd) &&
equalSlice(s.CapabilitiesDrop, service.CapabilitiesDrop) && equalSlice(s.CapabilitiesDrop, service.CapabilitiesDrop) &&
s.DependsOnContainer.Equal(service.DependsOnContainer) && s.DependsOnContainer.Equal(service.DependsOnContainer) &&
s.Deploy.Equal(service.Deploy) && s.Deploy.Equal(service.Deploy) &&
@ -673,6 +675,7 @@ func (s *Service) MergeExistingWin(service *Service) {
// fallthrough // fallthrough
default: default:
s.mergeExistingWinCommand(service.Command)
s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd) s.mergeExistingWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop) s.mergeExistingWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeExistingWinDependsOnContainer(service.DependsOnContainer) s.mergeExistingWinDependsOnContainer(service.DependsOnContainer)
@ -707,6 +710,7 @@ func (s *Service) MergeLastWin(service *Service) {
// fallthrough // fallthrough
default: default:
s.mergeLastWinCommand(service.Command)
s.mergeLastWinCapabilitiesAdd(service.CapabilitiesAdd) s.mergeLastWinCapabilitiesAdd(service.CapabilitiesAdd)
s.mergeLastWinCapabilitiesDrop(service.CapabilitiesDrop) s.mergeLastWinCapabilitiesDrop(service.CapabilitiesDrop)
s.mergeLastWinDependsOnContainer(service.DependsOnContainer) s.mergeLastWinDependsOnContainer(service.DependsOnContainer)
@ -723,6 +727,13 @@ func (s *Service) MergeLastWin(service *Service) {
} }
} }
func (s *Service) mergeExistingWinCommand(command []string) {
if len(s.Command) > 0 {
return
}
s.Command = command
}
func (s *Service) mergeExistingWinCapabilitiesAdd(capabilitiesAdd []string) { func (s *Service) mergeExistingWinCapabilitiesAdd(capabilitiesAdd []string) {
for _, capabilityAdd := range capabilitiesAdd { for _, capabilityAdd := range capabilitiesAdd {
if !existsInSlice(s.CapabilitiesAdd, capabilityAdd) && len(capabilityAdd) > 0 { if !existsInSlice(s.CapabilitiesAdd, capabilityAdd) && len(capabilityAdd) > 0 {
@ -935,6 +946,12 @@ func (s *Service) mergeExistingWinVolumes(volumes []string) {
} }
} }
func (s *Service) mergeLastWinCommand(command []string) {
if len(command) > 0 {
s.Command = command
}
}
func (s *Service) mergeLastWinCapabilitiesAdd(capabilitiesAdd []string) { func (s *Service) mergeLastWinCapabilitiesAdd(capabilitiesAdd []string) {
for _, capabilityAdd := range capabilitiesAdd { for _, capabilityAdd := range capabilitiesAdd {
if len(capabilityAdd) <= 0 { if len(capabilityAdd) <= 0 {
@ -1288,8 +1305,8 @@ func (sdoc *DependsOnContainer) Equal(equalable Equalable) bool {
// MarshalYAML implements the MarshalYAML interface to customize the behavior when being marshaled into a YAML document. // MarshalYAML implements the MarshalYAML interface to customize the behavior when being marshaled into a YAML document.
func (sdoc *DependsOnContainer) MarshalYAML() (interface{}, error) { func (sdoc *DependsOnContainer) MarshalYAML() (interface{}, error) {
var foundAnotherCondition bool = false var foundAnotherCondition = false
var dependencyNames []string var dependencyNames = make([]string, 0)
for dependencyName, dependencyDefinition := range sdoc.DependsOn { for dependencyName, dependencyDefinition := range sdoc.DependsOn {
if dependencyDefinition.Condition == ServiceDependsOnConditionServiceStarted { if dependencyDefinition.Condition == ServiceDependsOnConditionServiceStarted {

View File

@ -301,6 +301,7 @@ func TestService_Equal(t *testing.T) {
}, },
{ {
equalableA: &dockerCompose.Service{ equalableA: &dockerCompose.Service{
Command: []string{},
CapabilitiesAdd: []string{}, CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{}, CapabilitiesDrop: []string{},
DependsOnContainer: &dockerCompose.DependsOnContainer{}, DependsOnContainer: &dockerCompose.DependsOnContainer{},
@ -316,6 +317,7 @@ func TestService_Equal(t *testing.T) {
Volumes: []string{}, Volumes: []string{},
}, },
equalableB: &dockerCompose.Service{ equalableB: &dockerCompose.Service{
Command: []string{},
CapabilitiesAdd: []string{}, CapabilitiesAdd: []string{},
CapabilitiesDrop: []string{}, CapabilitiesDrop: []string{},
DependsOnContainer: &dockerCompose.DependsOnContainer{}, DependsOnContainer: &dockerCompose.DependsOnContainer{},
@ -332,6 +334,15 @@ func TestService_Equal(t *testing.T) {
}, },
expectedResult: true, expectedResult: true,
}, },
{
equalableA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
equalableB: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
expectedResult: true,
},
{ {
equalableA: &dockerCompose.Service{ equalableA: &dockerCompose.Service{
CapabilitiesAdd: []string{"NET_ADMIN"}, CapabilitiesAdd: []string{"NET_ADMIN"},
@ -636,6 +647,52 @@ func TestService_MergeExistingWin(t *testing.T) {
expectedService: &dockerCompose.Service{}, expectedService: &dockerCompose.Service{},
}, },
// Command
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{""},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
// CapabilitiesAdd // CapabilitiesAdd
{ {
serviceDeploymentA: &dockerCompose.Service{ serviceDeploymentA: &dockerCompose.Service{
@ -1620,6 +1677,52 @@ func TestService_MergeLastWin(t *testing.T) {
expectedService: &dockerCompose.Service{}, expectedService: &dockerCompose.Service{},
}, },
// Command
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
expectedService: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
},
{
serviceDeploymentA: &dockerCompose.Service{
Command: []string{"/usr/bin/cp", "--recursive", "/tmp/foo.txt", "/tmp/bar.txt"},
},
serviceDeploymentB: &dockerCompose.Service{
Command: []string{""},
},
expectedService: &dockerCompose.Service{
Command: []string{""},
},
},
// CapabilitiesAdd // CapabilitiesAdd
{ {
serviceDeploymentA: &dockerCompose.Service{ serviceDeploymentA: &dockerCompose.Service{

View File

@ -55,8 +55,8 @@ func EqualStringMap[R Equalable](mapA, mapB map[string]R) bool {
// ExistsInMap returns true if object of type any exists under the passed name. // ExistsInMap returns true if object of type any exists under the passed name.
func ExistsInMap[T any](m map[string]T, name string) bool { func ExistsInMap[T any](m map[string]T, name string) bool {
switch { switch m {
case m == nil: case nil:
return false return false
default: default:
_, present := m[name] _, present := m[name]

View File

@ -0,0 +1,4 @@
services:
frontend:
command: [ "/usr/bin/cp", "--recursive", "--force", "/tmp/foo.txt", "/tmp/bar.txt" ]
image: library/frontend:latest

View File

@ -0,0 +1,4 @@
services:
frontend:
command: [ "/usr/bin/cp", "--recursive", "--force", "/tmp/bar.txt", "/tmp/foo.txt"]
image: library/frontend:latest

View File

@ -0,0 +1,9 @@
services:
frontend:
command:
- /usr/bin/cp
- --recursive
- --force
- /tmp/foo.txt
- /tmp/bar.txt
image: library/frontend:latest

View File

@ -20,15 +20,15 @@ func Fetch(urls ...string) ([]*dockerCompose.Config, error) {
return nil, err return nil, err
} }
switch { switch dockerComposeURL.Scheme {
case dockerComposeURL.Scheme == "http" || dockerComposeURL.Scheme == "https": case "http", "https":
dockerComposeConfig, err := getDockerComposeViaHTTP(dockerComposeURL.String()) dockerComposeConfig, err := getDockerComposeViaHTTP(dockerComposeURL.String())
if err != nil { if err != nil {
return nil, err return nil, err
} }
dockerComposeConfigs = append(dockerComposeConfigs, dockerComposeConfig) dockerComposeConfigs = append(dockerComposeConfigs, dockerComposeConfig)
case dockerComposeURL.Scheme == "file": case "file":
fallthrough fallthrough
default: default:
dockerComposeConfig, err := readDockerComposeFromFile(dockerComposeURL.Path) dockerComposeConfig, err := readDockerComposeFromFile(dockerComposeURL.Path)
@ -43,7 +43,7 @@ func Fetch(urls ...string) ([]*dockerCompose.Config, error) {
return dockerComposeConfigs, nil return dockerComposeConfigs, nil
} }
var ErrorPathIsDir error = errors.New("Path is a directory") var ErrorPathIsDir error = errors.New("path is a directory")
func getDockerComposeViaHTTP(url string) (*dockerCompose.Config, error) { func getDockerComposeViaHTTP(url string) (*dockerCompose.Config, error) {
req, err := http.NewRequest(http.MethodGet, url, nil) req, err := http.NewRequest(http.MethodGet, url, nil)
@ -55,10 +55,10 @@ func getDockerComposeViaHTTP(url string) (*dockerCompose.Config, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer resp.Body.Close() defer func() { _ = resp.Body.Close() }()
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Received unexpected HTTP-Statuscode %v", resp.StatusCode) return nil, fmt.Errorf("received unexpected HTTP-Statuscode %v", resp.StatusCode)
} }
dockerCompose := dockerCompose.NewConfig() dockerCompose := dockerCompose.NewConfig()
@ -85,7 +85,7 @@ func readDockerComposeFromFile(name string) (*dockerCompose.Config, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer file.Close() defer func() { _ = file.Close() }()
dockerCompose := dockerCompose.NewConfig() dockerCompose := dockerCompose.NewConfig()