You've already forked dcmerge
							
							Initial Commit
This commit is contained in:
		
							
								
								
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| dcmerge | ||||
							
								
								
									
										862
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										862
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,862 @@ | ||||
| --- | ||||
| kind: pipeline | ||||
| type: kubernetes | ||||
| name: linter | ||||
|  | ||||
| clone: | ||||
|   disable: true | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: markdown lint | ||||
|   commands: | ||||
|   - markdownlint *.md | ||||
|   image: git.cryptic.systems/volker.raschek/markdownlint:0.35.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.2 | ||||
|   resources: | ||||
|     limits: | ||||
|       cpu: 150 | ||||
|       memory: 150M | ||||
|   when: | ||||
|     status: | ||||
|     - changed | ||||
|     - failure | ||||
|  | ||||
| trigger: | ||||
|   event: | ||||
|     exclude: | ||||
|     - tag | ||||
|  | ||||
| --- | ||||
| kind: pipeline | ||||
| type: docker | ||||
| name: dry-run-amd64 | ||||
|  | ||||
| clone: | ||||
|   disable: true | ||||
|  | ||||
| depends_on: | ||||
| - linter | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: amd64 | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   when: | ||||
|     status: | ||||
|     - changed | ||||
|     - failure | ||||
|  | ||||
| trigger: | ||||
|   branch: | ||||
|     exclude: | ||||
|     - master | ||||
|   event: | ||||
|   - pull_request | ||||
|   - push | ||||
|   repo: | ||||
|   - volker.raschek/dcmerge | ||||
|  | ||||
| --- | ||||
| kind: pipeline | ||||
| type: docker | ||||
| name: dry-run-arm-v7 | ||||
|  | ||||
| clone: | ||||
|   disable: true | ||||
|  | ||||
| depends_on: | ||||
| - linter | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: arm | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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-arm-v7 | ||||
|     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.2 | ||||
|   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 | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: arm64 | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   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 | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: amd64 | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   when: | ||||
|     status: | ||||
|     - changed | ||||
|     - failure | ||||
|  | ||||
| trigger: | ||||
|   branch: | ||||
|   - master | ||||
|   event: | ||||
|   - cron | ||||
|   - push | ||||
|   repo: | ||||
|   - volker.raschek/dcmerge | ||||
|  | ||||
| --- | ||||
| kind: pipeline | ||||
| type: docker | ||||
| name: latest-arm-v7 | ||||
|  | ||||
| clone: | ||||
|   disable: true | ||||
|  | ||||
| depends_on: | ||||
| - linter | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: arm | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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-arm-v7 | ||||
|     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.2 | ||||
|   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 | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: arm64 | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   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-arm-v7 | ||||
| - 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.2.1 | ||||
|  | ||||
| - 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.2 | ||||
|   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.2.1 | ||||
|  | ||||
| - 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.13.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.2 | ||||
|   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.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   when: | ||||
|     status: | ||||
|     - changed | ||||
|     - failure | ||||
|  | ||||
| trigger: | ||||
|   event: | ||||
|   - tag | ||||
|   repo: | ||||
|   - volker.raschek/dcmerge | ||||
|  | ||||
| --- | ||||
| kind: pipeline | ||||
| type: docker | ||||
| name: tagged-arm-v7 | ||||
|  | ||||
| clone: | ||||
|   disable: true | ||||
|  | ||||
| platform: | ||||
|   os: linux | ||||
|   arch: arm | ||||
|  | ||||
| steps: | ||||
| - name: clone | ||||
|   image: git.cryptic.systems/volker.raschek/git:1.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   settings: | ||||
|     auto_tag: true | ||||
|     auto_tag_suffix: arm-v7 | ||||
|     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.2 | ||||
|   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.2.1 | ||||
|  | ||||
| - name: build | ||||
|   image: docker.io/plugins/docker:20.10.9 | ||||
|   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.2 | ||||
|   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-arm-v7 | ||||
| - 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.2.1 | ||||
|  | ||||
| - 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.2 | ||||
|   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.2.1 | ||||
|  | ||||
| - 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.13.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.2 | ||||
|   resources: | ||||
|     limits: | ||||
|       cpu: 150 | ||||
|       memory: 150M | ||||
|   when: | ||||
|     status: | ||||
|     - changed | ||||
|     - failure | ||||
|  | ||||
| trigger: | ||||
|   event: | ||||
|   - tag | ||||
|   repo: | ||||
|   - volker.raschek/dcmerge | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| dcmerge | ||||
							
								
								
									
										143
									
								
								.markdownlint.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								.markdownlint.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| # markdownlint YAML configuration | ||||
| # https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml | ||||
|  | ||||
| # Default state for all rules | ||||
| default: true | ||||
|  | ||||
| # Path to configuration file to extend | ||||
| extends: null | ||||
|  | ||||
| # MD003/heading-style/header-style - Heading style | ||||
| MD003: | ||||
|   # Heading style | ||||
|   style: "atx" | ||||
|  | ||||
| # MD004/ul-style - Unordered list style | ||||
| MD004: | ||||
|   style: "dash" | ||||
|  | ||||
| # MD007/ul-indent - Unordered list indentation | ||||
| MD007: | ||||
|   # Spaces for indent | ||||
|   indent: 2 | ||||
|   # Whether to indent the first level of the list | ||||
|   start_indented: false | ||||
|  | ||||
| # MD009/no-trailing-spaces - Trailing spaces | ||||
| MD009: | ||||
|   # Spaces for line break | ||||
|   br_spaces: 2 | ||||
|   # Allow spaces for empty lines in list items | ||||
|   list_item_empty_lines: false | ||||
|   # Include unnecessary breaks | ||||
|   strict: false | ||||
|  | ||||
| # MD010/no-hard-tabs - Hard tabs | ||||
| MD010: | ||||
|   # Include code blocks | ||||
|   code_blocks: true | ||||
|  | ||||
| # MD012/no-multiple-blanks - Multiple consecutive blank lines | ||||
| MD012: | ||||
|   # Consecutive blank lines | ||||
|   maximum: 1 | ||||
|  | ||||
| # MD013/line-length - Line length | ||||
| MD013: | ||||
|   # Number of characters | ||||
|   line_length: 80 | ||||
|   # Number of characters for headings | ||||
|   heading_line_length: 80 | ||||
|   # Number of characters for code blocks | ||||
|   code_block_line_length: 80 | ||||
|   # Include code blocks | ||||
|   code_blocks: false | ||||
|   # Include tables | ||||
|   tables: false | ||||
|   # Include headings | ||||
|   headings: true | ||||
|   # Include headings | ||||
|   headers: true | ||||
|   # Strict length checking | ||||
|   strict: false | ||||
|   # Stern length checking | ||||
|   stern: false | ||||
|  | ||||
| # MD022/blanks-around-headings/blanks-around-headers - Headings should be surrounded by blank lines | ||||
| MD022: | ||||
|   # Blank lines above heading | ||||
|   lines_above: 1 | ||||
|   # Blank lines below heading | ||||
|   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: | ||||
|   # Heading level | ||||
|   level: 1 | ||||
|   # RegExp for matching title in front matter | ||||
|   front_matter_title: "^\\s*title\\s*[:=]" | ||||
|  | ||||
| # MD026/no-trailing-punctuation - Trailing punctuation in heading | ||||
| MD026: | ||||
|   # Punctuation characters | ||||
|   punctuation: ".,;:!。,;:!" | ||||
|  | ||||
| # MD029/ol-prefix - Ordered list item prefix | ||||
| MD029: | ||||
|   # List style | ||||
|   style: "one_or_ordered" | ||||
|  | ||||
| # MD030/list-marker-space - Spaces after list markers | ||||
| MD030: | ||||
|   # Spaces for single-line unordered list items | ||||
|   ul_single: 1 | ||||
|   # Spaces for single-line ordered list items | ||||
|   ol_single: 1 | ||||
|   # Spaces for multi-line unordered list items | ||||
|   ul_multi: 1 | ||||
|   # Spaces for multi-line ordered list items | ||||
|   ol_multi: 1 | ||||
|  | ||||
| # MD033/no-inline-html - Inline HTML | ||||
| MD033: | ||||
|   # Allowed elements | ||||
|   allowed_elements: [] | ||||
|  | ||||
| # MD035/hr-style - Horizontal rule style | ||||
| MD035: | ||||
|   # Horizontal rule style | ||||
|   style: "---" | ||||
|  | ||||
| # MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading | ||||
| MD036: | ||||
|   # Punctuation characters | ||||
|   punctuation: ".,;:!?。,;:!?" | ||||
|  | ||||
| # MD041/first-line-heading/first-line-h1 - First line in a file should be a top-level heading | ||||
| MD041: | ||||
|   # Heading level | ||||
|   level: 1 | ||||
|   # RegExp for matching title in front matter | ||||
|   front_matter_title: "^\\s*title\\s*[:=]" | ||||
|  | ||||
| # MD044/proper-names - Proper names should have the correct capitalization | ||||
| MD044: | ||||
|   # List of proper names | ||||
|   names: [] | ||||
|   # Include code blocks | ||||
|   code_blocks: false | ||||
|  | ||||
| # MD046/code-block-style - Code block style | ||||
| MD046: | ||||
|   # Block style | ||||
|   style: "fenced" | ||||
|  | ||||
| # MD048/code-fence-style - Code fence style | ||||
| MD048: | ||||
|   # Code fence syle | ||||
|   style: "backtick" | ||||
							
								
								
									
										20
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| FROM docker.io/library/golang:1.20.6-alpine3.18 AS build | ||||
|  | ||||
| RUN apk add git make | ||||
|  | ||||
| WORKDIR /workspace | ||||
| ADD ./ /workspace | ||||
|  | ||||
| RUN make install \ | ||||
|       DESTDIR=/cache \ | ||||
|       PREFIX=/usr \ | ||||
|       VERSION=${VERSION} | ||||
|  | ||||
| FROM docker.io/library/alpine:3.18.2 | ||||
|  | ||||
| COPY --from=build /cache / | ||||
|  | ||||
| WORKDIR /workspace | ||||
| VOLUME [ "/workspace" ] | ||||
|  | ||||
| ENTRYPOINT [ "/usr/bin/dcmerge" ] | ||||
							
								
								
									
										20
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| Copyright (c) 2023 Markus Pesch | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining | ||||
| a copy of this software and associated documentation files (the | ||||
| "Software"), to deal in the Software without restriction, including | ||||
| without limitation the rights to use, copy, modify, merge, publish, | ||||
| distribute, sublicense, and/or sell copies of the Software, and to | ||||
| permit persons to whom the Software is furnished to do so, subject to | ||||
| the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be | ||||
| included in all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
							
								
								
									
										114
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| EXECUTABLE=dcmerge | ||||
| VERSION?=$(shell git describe --abbrev=0)+hash.$(shell git rev-parse --short HEAD) | ||||
|  | ||||
| # Destination directory and prefix to place the compiled binaries, documentaions | ||||
| # and other files. | ||||
| DESTDIR?= | ||||
| PREFIX?=/usr/local | ||||
|  | ||||
| # CONTAINER_RUNTIME | ||||
| # The CONTAINER_RUNTIME variable will be used to specified the path to a | ||||
| # container runtime. This is needed to start and run a container image. | ||||
| CONTAINER_RUNTIME?=$(shell which podman) | ||||
|  | ||||
| # DCMERGE_IMAGE_REGISTRY_NAME | ||||
| # Defines the name of the new container to be built using several variables. | ||||
| DCMERGE_IMAGE_REGISTRY_NAME:=git.cryptic.systems | ||||
| DCMERGE_IMAGE_REGISTRY_USER:=volker.raschek | ||||
|  | ||||
| DCMERGE_IMAGE_NAMESPACE?=${DCMERGE_IMAGE_REGISTRY_USER} | ||||
| DCMERGE_IMAGE_NAME:=${EXECUTABLE} | ||||
| DCMERGE_IMAGE_VERSION?=latest | ||||
| 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 | ||||
| # ============================================================================== | ||||
| dcmerge: | ||||
| 	CGO_ENABLED=0 \ | ||||
| 	GOPRIVATE=$(shell go env GOPRIVATE) \ | ||||
| 	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 | ||||
|  | ||||
| # CLEAN | ||||
| # ============================================================================== | ||||
| PHONY+=clean | ||||
| clean: | ||||
| 	rm --force --recursive dcmerge | ||||
|  | ||||
| # TESTS | ||||
| # ============================================================================== | ||||
| PHONY+=test/unit | ||||
| test/unit: | ||||
| 	go test -v -p 1 -coverprofile=coverage.txt -covermode=count -timeout 1200s ./pkg/... | ||||
|  | ||||
| PHONY+=test/integration | ||||
| test/integration: | ||||
| 	go test -v -p 1 -count=1 -timeout 1200s ./it/... | ||||
|  | ||||
| PHONY+=test/coverage | ||||
| test/coverage: test/unit | ||||
| 	go tool cover -html=coverage.txt | ||||
|  | ||||
| # GOLANGCI-LINT | ||||
| # ============================================================================== | ||||
| PHONY+=golangci-lint | ||||
| golangci-lint: | ||||
| 	golangci-lint run --concurrency=$(shell nproc) | ||||
|  | ||||
| # INSTALL | ||||
| # ============================================================================== | ||||
| PHONY+=uninstall | ||||
| install: dcmerge | ||||
| 	install --directory ${DESTDIR}/etc/bash_completion.d | ||||
| 	./dcmerge completion bash > ${DESTDIR}/etc/bash_completion.d/${EXECUTABLE} | ||||
|  | ||||
| 	install --directory ${DESTDIR}${PREFIX}/bin | ||||
| 	install --mode 0755 ${EXECUTABLE} ${DESTDIR}${PREFIX}/bin/${EXECUTABLE} | ||||
|  | ||||
| 	install --directory ${DESTDIR}${PREFIX}/share/licenses/${EXECUTABLE} | ||||
| 	install --mode 0644 LICENSE ${DESTDIR}${PREFIX}/share/licenses/${EXECUTABLE}/LICENSE | ||||
|  | ||||
| # UNINSTALL | ||||
| # ============================================================================== | ||||
| PHONY+=uninstall | ||||
| uninstall: | ||||
| 	-rm --force --recursive \ | ||||
| 		${DESTDIR}/etc/bash_completion.d/${EXECUTABLE} \ | ||||
| 		${DESTDIR}${PREFIX}/bin/${EXECUTABLE} \ | ||||
| 		${DESTDIR}${PREFIX}/share/licenses/${EXECUTABLE} | ||||
|  | ||||
| # BUILD CONTAINER IMAGE | ||||
| # ============================================================================== | ||||
| PHONY+=container-image/build | ||||
| container-image/build: | ||||
| 	${CONTAINER_RUNTIME} build \ | ||||
| 		--build-arg VERSION=${VERSION} \ | ||||
| 		--file Dockerfile \ | ||||
| 		--no-cache \ | ||||
| 		--pull \ | ||||
| 		--tag ${DCMERGE_IMAGE_FULLY_QUALIFIED} \ | ||||
| 		--tag ${DCMERGE_IMAGE_UNQUALIFIED} \ | ||||
| 		. | ||||
|  | ||||
| # DELETE CONTAINER IMAGE | ||||
| # ============================================================================== | ||||
| PHONY:=container-image/delete | ||||
| container-image/delete: | ||||
| 	- ${CONTAINER_RUNTIME} image rm ${DCMERGE_IMAGE_FULLY_QUALIFIED} ${DCMERGE_IMAGE_UNQUALIFIED} | ||||
|  | ||||
| # PUSH CONTAINER IMAGE | ||||
| # ============================================================================== | ||||
| PHONY+=container-image/push | ||||
| container-image/push: | ||||
| 	echo ${DCMERGE_IMAGE_REGISTRY_PASSWORD} | ${CONTAINER_RUNTIME} login ${DCMERGE_IMAGE_REGISTRY_NAME} --username ${DCMERGE_IMAGE_REGISTRY_USER} --password-stdin | ||||
| 	${CONTAINER_RUNTIME} push ${DCMERGE_IMAGE_FULLY_QUALIFIED} | ||||
|  | ||||
| # PHONY | ||||
| # ============================================================================== | ||||
| # Declare the contents of the PHONY variable as phony.  We keep that information | ||||
| # in a variable so we can use it in if_changed. | ||||
| .PHONY: ${PHONY} | ||||
							
								
								
									
										129
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| # dcmerge | ||||
|  | ||||
| [](https://drone.cryptic.systems/volker.raschek/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. | ||||
|  | ||||
| The dynamic pattern of a docker-compose file, that for example `environments` | ||||
| can be specified as a string slice or a list of objects is currently not | ||||
| supported. `dcmerge` expect a strict pattern layout. The `environments`, `ports` | ||||
| and `volumes` must be declared as a slice of strings. | ||||
|  | ||||
| Dockercompose file can be read-in from different sources. Currently are the | ||||
| following sources supported: | ||||
|  | ||||
| - File | ||||
| - HTTP/HTTPS | ||||
|  | ||||
| Furthermore, `dcmerge` support different ways to merge multiple docker-compose | ||||
| files. | ||||
|  | ||||
| - The default merge, add missing secrets, services, networks and volumes. | ||||
| - The existing-win merge, add and protect existing attributes. | ||||
| - The last-win merge, add or overwrite existing attributes. | ||||
|  | ||||
| ## default | ||||
|  | ||||
| Merge only missing secrets, services, networks and volumes without respecting | ||||
| their attributes. For example, when the service `app` is already declared, it is | ||||
| not possible to add the service `app` twice. The second service will be | ||||
| completely skipped. | ||||
|  | ||||
| ```yaml | ||||
| --- | ||||
| # cat ~/docker-compose-A.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=HelloWorld123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| --- | ||||
| # cat ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     image: app/name:2.3.0 | ||||
|     volume: | ||||
|     - /etc/localtime:/etc/localtime | ||||
|     - /dev/urandom:/etc/urandom | ||||
|   db: | ||||
|     image: postgres | ||||
|     volume: | ||||
|     - /etc/localtime:/etc/localtime | ||||
|     - /dev/urandom:/etc/urandom | ||||
| --- | ||||
| # dcmerge ~/docker-compose-A.yaml ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=HelloWorld123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
|   db: | ||||
|     image: postgres | ||||
|     volume: | ||||
|     - /etc/localtime:/etc/localtime | ||||
|     - /dev/urandom:/etc/urandom | ||||
| ``` | ||||
|  | ||||
| ## existing-win | ||||
|  | ||||
| The existing-win merge protects existing attributes. For example there are two | ||||
| different docker-compose files, but booth has the same environment variable | ||||
| `CLIENT_SECRET` defined with different values. The first declaration of the | ||||
| attribute wins and is for overwriting protected. | ||||
|  | ||||
| ```yaml | ||||
| --- | ||||
| # cat ~/docker-compose-A.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=HelloWorld123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| --- | ||||
| # cat ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=FooBar123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| --- | ||||
| # dcmerge --existing-win ~/docker-compose-A.yaml ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=HelloWorld123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| ``` | ||||
|  | ||||
| ## last-win | ||||
|  | ||||
| The last-win merge overwrite recursive existing attributes. For example there | ||||
| are two different docker-compose files, but booth has the same environment | ||||
| variable `CLIENT_SECRET` defined with different values. The last passed | ||||
| docker-compose file which contains this environment wins. | ||||
|  | ||||
| ```yaml | ||||
| --- | ||||
| # cat ~/docker-compose-A.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=HelloWorld123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| --- | ||||
| # cat ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=FooBar123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| --- | ||||
| # dcmerge --last-win ~/docker-compose-A.yaml ~/docker-compose-B.yaml | ||||
| services: | ||||
|   app: | ||||
|     environments: | ||||
|     - CLIENT_SECRET=FooBar123 | ||||
|     image: example.local/app/name:0.1.0 | ||||
| ``` | ||||
							
								
								
									
										101
									
								
								cmd/root.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								cmd/root.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
| 	"git.cryptic.systems/volker.raschek/dcmerge/pkg/domain/dockerCompose" | ||||
| 	"git.cryptic.systems/volker.raschek/dcmerge/pkg/fetcher" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"gopkg.in/yaml.v2" | ||||
| ) | ||||
|  | ||||
| func Execute(version string) error { | ||||
| 	completionCmd := &cobra.Command{ | ||||
| 		Use:                   "completion [bash|zsh|fish|powershell]", | ||||
| 		Short:                 "Generate completion script", | ||||
| 		Long:                  "To load completions", | ||||
| 		DisableFlagsInUseLine: true, | ||||
| 		ValidArgs:             []string{"bash", "zsh", "fish", "powershell"}, | ||||
| 		Args:                  cobra.ExactValidArgs(1), | ||||
| 		Run: func(cmd *cobra.Command, args []string) { | ||||
| 			switch args[0] { | ||||
| 			case "bash": | ||||
| 				cmd.Root().GenBashCompletion(os.Stdout) | ||||
| 			case "zsh": | ||||
| 				cmd.Root().GenZshCompletion(os.Stdout) | ||||
| 			case "fish": | ||||
| 				cmd.Root().GenFishCompletion(os.Stdout, true) | ||||
| 			case "powershell": | ||||
| 				cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout) | ||||
| 			} | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	rootCmd := &cobra.Command{ | ||||
| 		Use:   "dcmerge", | ||||
| 		Args:  cobra.MinimumNArgs(2), | ||||
| 		Short: "Merge docker-compose files from multiple resources", | ||||
| 		Example: `dcmerge docker-compose.yml ./integration-test/docker-compose.yml | ||||
| dcmerge docker-compose.yml https://git.example.local/user/repo/docker-compose.yml`, | ||||
| 		RunE:    run, | ||||
| 		Version: version, | ||||
| 	} | ||||
| 	rootCmd.Flags().BoolP("last-merge", "l", false, "Overwrite existing attributes") | ||||
| 	rootCmd.Flags().BoolP("output-file", "o", false, "Write instead on stdout into a file") | ||||
| 	rootCmd.AddCommand(completionCmd) | ||||
|  | ||||
| 	return rootCmd.Execute() | ||||
| } | ||||
|  | ||||
| func run(cmd *cobra.Command, args []string) error { | ||||
| 	mergeLastWin, err := cmd.Flags().GetBool("last-merge") | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Failed to parse flag last-merge: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	outputFile, err := cmd.Flags().GetString("output-file") | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Failed to parse flag output-file: %s", err) | ||||
| 	} | ||||
|  | ||||
| 	dockerComposeConfig := dockerCompose.NewConfig() | ||||
|  | ||||
| 	dockerComposeConfigs, err := fetcher.Fetch(args...) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, config := range dockerComposeConfigs { | ||||
| 		switch { | ||||
| 		case mergeLastWin: | ||||
| 			dockerComposeConfig.MergeLastWin(config) | ||||
| 		default: | ||||
| 			dockerComposeConfig.Merge(config) | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	switch { | ||||
| 	case len(outputFile) > 0: | ||||
| 		err = os.MkdirAll(filepath.Dir(outputFile), 0755) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		f, err := os.Create(outputFile) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		defer f.Close() | ||||
|  | ||||
| 		yamlEncoder := yaml.NewEncoder(f) | ||||
| 		return yamlEncoder.Encode(dockerComposeConfig) | ||||
|  | ||||
| 	default: | ||||
| 		yamlEncoder := yaml.NewEncoder(os.Stdout) | ||||
| 		return yamlEncoder.Encode(dockerComposeConfig) | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										17
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| module git.cryptic.systems/volker.raschek/dcmerge | ||||
|  | ||||
| go 1.20 | ||||
|  | ||||
| require ( | ||||
| 	github.com/spf13/cobra v1.7.0 | ||||
| 	github.com/stretchr/testify v1.8.4 | ||||
| 	gopkg.in/yaml.v2 v2.4.0 | ||||
| 	gopkg.in/yaml.v3 v3.0.1 | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||
| 	github.com/spf13/pflag v1.0.5 // indirect | ||||
| ) | ||||
							
								
								
									
										20
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||||
| github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||||
| github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= | ||||
| github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= | ||||
| github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||||
| github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||||
| github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||||
| github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/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= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
							
								
								
									
										9
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package main | ||||
|  | ||||
| import "git.cryptic.systems/volker.raschek/dcmerge/cmd" | ||||
|  | ||||
| var version string | ||||
|  | ||||
| func main() { | ||||
| 	cmd.Execute(version) | ||||
| } | ||||
							
								
								
									
										26
									
								
								manifest.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								manifest.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| 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}}-arm-v7 | ||||
|     platform: | ||||
|       architecture: arm | ||||
|       os: linux | ||||
|       variant: v7 | ||||
|   - | ||||
|     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 | ||||
							
								
								
									
										1210
									
								
								pkg/domain/dockerCompose/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1210
									
								
								pkg/domain/dockerCompose/config.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2093
									
								
								pkg/domain/dockerCompose/config_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2093
									
								
								pkg/domain/dockerCompose/config_test.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										65
									
								
								pkg/domain/dockerCompose/equalable.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								pkg/domain/dockerCompose/equalable.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| package dockerCompose | ||||
|  | ||||
| type Equalable interface { | ||||
| 	Equal(equalable Equalable) bool | ||||
| } | ||||
|  | ||||
| // Contains returns true when sliceA is in sliceB. | ||||
| func Contains[R Equalable](sliceA, sliceB []R) bool { | ||||
| 	switch { | ||||
| 	case sliceA == nil && sliceB == nil: | ||||
| 		return true | ||||
| 	case sliceA != nil && sliceB == nil: | ||||
| 		return false | ||||
| 	case sliceA == nil && sliceB != nil: | ||||
| 		return false | ||||
| 	default: | ||||
| 	LOOP: | ||||
| 		for i := range sliceA { | ||||
| 			for j := range sliceB { | ||||
| 				if sliceA[i].Equal(sliceB[j]) { | ||||
| 					continue LOOP | ||||
| 				} | ||||
| 			} | ||||
| 			return false | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Equal returns true when sliceA and sliceB are equal. | ||||
| func Equal[R Equalable](sliceA, sliceB []R) bool { | ||||
| 	return Contains(sliceA, sliceB) && | ||||
| 		Contains(sliceB, sliceA) && | ||||
| 		len(sliceA) == len(sliceB) | ||||
| } | ||||
|  | ||||
| // Equal returns true when booth string maps of Equalable are equal. | ||||
| func EqualStringMap[R Equalable](mapA, mapB map[string]R) bool { | ||||
| 	equalFunc := func(mapA, mapB map[string]R) bool { | ||||
| 	LOOP: | ||||
| 		for keyA, valueA := range mapA { | ||||
| 			for keyB, valueB := range mapB { | ||||
| 				if keyA == keyB && | ||||
| 					valueA.Equal(valueB) { | ||||
| 					continue LOOP | ||||
| 				} | ||||
| 			} | ||||
| 			return false | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  | ||||
| 	return equalFunc(mapA, mapB) && equalFunc(mapB, mapA) | ||||
| } | ||||
|  | ||||
| // ExistsInMap returns true if object of type any exists under the passed name. | ||||
| func ExistsInMap[T any](m map[string]T, name string) bool { | ||||
| 	switch { | ||||
| 	case m == nil: | ||||
| 		return false | ||||
| 	default: | ||||
| 		_, present := m[name] | ||||
| 		return present | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										99
									
								
								pkg/fetcher/fetcher.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								pkg/fetcher/fetcher.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| package fetcher | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
|  | ||||
| 	"git.cryptic.systems/volker.raschek/dcmerge/pkg/domain/dockerCompose" | ||||
| 	"gopkg.in/yaml.v3" | ||||
| ) | ||||
|  | ||||
| func Fetch(urls ...string) ([]*dockerCompose.Config, error) { | ||||
| 	dockerComposeConfigs := make([]*dockerCompose.Config, 0) | ||||
|  | ||||
| 	for _, rawURL := range urls { | ||||
| 		dockerComposeURL, err := url.Parse(rawURL) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		switch { | ||||
| 		case dockerComposeURL.Scheme == "http" || dockerComposeURL.Scheme == "https": | ||||
| 			dockerComposeConfig, err := getDockerComposeViaHTTP(dockerComposeURL.String()) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			dockerComposeConfigs = append(dockerComposeConfigs, dockerComposeConfig) | ||||
| 		case dockerComposeURL.Scheme == "file": | ||||
| 			fallthrough | ||||
| 		default: | ||||
| 			dockerComposeConfig, err := readDockerComposeFromFile(dockerComposeURL.Path) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
|  | ||||
| 			dockerComposeConfigs = append(dockerComposeConfigs, dockerComposeConfig) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return dockerComposeConfigs, nil | ||||
| } | ||||
|  | ||||
| var ErrorPathIsDir error = errors.New("Path is a directory") | ||||
|  | ||||
| func getDockerComposeViaHTTP(url string) (*dockerCompose.Config, error) { | ||||
| 	req, err := http.NewRequest(http.MethodGet, url, nil) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	resp, err := http.DefaultClient.Do(req) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
|  | ||||
| 	if resp.StatusCode != http.StatusOK { | ||||
| 		return nil, fmt.Errorf("Received unexpected HTTP-Statuscode %v", resp.StatusCode) | ||||
| 	} | ||||
|  | ||||
| 	dockerCompose := dockerCompose.NewConfig() | ||||
|  | ||||
| 	yamlDecoder := yaml.NewDecoder(resp.Body) | ||||
| 	err = yamlDecoder.Decode(&dockerCompose) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return dockerCompose, nil | ||||
| } | ||||
|  | ||||
| func readDockerComposeFromFile(name string) (*dockerCompose.Config, error) { | ||||
| 	fileStat, err := os.Stat(name) | ||||
| 	switch { | ||||
| 	case errors.Is(err, os.ErrNotExist): | ||||
| 		return nil, err | ||||
| 	case fileStat.IsDir(): | ||||
| 		return nil, fmt.Errorf("%w: %s", ErrorPathIsDir, name) | ||||
| 	} | ||||
|  | ||||
| 	file, err := os.Open(name) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer file.Close() | ||||
|  | ||||
| 	dockerCompose := dockerCompose.NewConfig() | ||||
|  | ||||
| 	yamlDecoder := yaml.NewDecoder(file) | ||||
| 	err = yamlDecoder.Decode(&dockerCompose) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	return dockerCompose, nil | ||||
| } | ||||
							
								
								
									
										31
									
								
								renovate.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								renovate.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| { | ||||
|   "$schema": "https://docs.renovatebot.com/renovate-schema.json", | ||||
|   "assignees": [ "volker.raschek" ], | ||||
|   "automergeStrategy": "merge-commit", | ||||
|   "automergeType": "pr", | ||||
|   "labels": [ "renovate" ], | ||||
|   "packageRules": [ | ||||
|     { | ||||
|       "addLabels": [ "renovate/droneci", "renovate/automerge" ], | ||||
|       "automerge": true, | ||||
|       "matchManagers": "droneci", | ||||
|       "matchUpdateTypes": [ "minor", "patch"] | ||||
|     }, | ||||
|     { | ||||
|       "description": "Automatically update patch version of used container images in docker files", | ||||
|       "addLabels": [ "renovate/container-image", "renovate/automerge" ], | ||||
|       "automerge": true, | ||||
|       "matchBaseBranches": [ "master" ], | ||||
|       "matchManagers": [ "dockerfile" ], | ||||
|       "matchUpdateTypes": [ "patch" ] | ||||
|     }, | ||||
|     { | ||||
|       "addLabels": [ "renovate/dcmerge", "renovate/automerge" ], | ||||
|       "automerge": false, | ||||
|       "matchPackageNames": [ "dcmerge" ], | ||||
|       "matchManagers": [ "regex" ] | ||||
|     } | ||||
|   ], | ||||
|   "rebaseLabel": "renovate/rebase", | ||||
|   "rebaseWhen": "behind-base-branch" | ||||
| } | ||||
		Reference in New Issue
	
	Block a user