Compare commits
4 commits
main
...
verbose-er
Author | SHA1 | Date | |
---|---|---|---|
c182505b76 | |||
07cf60ba59 | |||
8cb17dea54 | |||
0a9efe85d2 |
82 changed files with 875 additions and 2238 deletions
42
.github/workflows/stable.yml
vendored
Normal file
42
.github/workflows/stable.yml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
name: stable
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: stable build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
- name: build stable release
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_DDA }}
|
||||
run: |
|
||||
pyb -P version=${{ github.ref }} publish upload
|
||||
|
||||
- name: Create GH Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: Release ${{ github.ref }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
30
.github/workflows/unstable.yml
vendored
Normal file
30
.github/workflows/unstable.yml
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
name: unstable
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '![0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: unstable
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Use python 3.x
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
|
||||
- name: build unstable release
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_DDA }}
|
||||
run: |
|
||||
pyb publish upload
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -109,6 +109,3 @@ venv.bak/
|
|||
|
||||
.clj-kondo/
|
||||
.lsp/
|
||||
.calva/
|
||||
.cpcache/
|
||||
infrastructure/backup/image/resources/backup-repository-state.edn
|
||||
|
|
|
@ -1,89 +1,17 @@
|
|||
stages:
|
||||
- lint&test
|
||||
- upload
|
||||
- image
|
||||
image: "domaindrivenarchitecture/devops-build:4.0.8"
|
||||
|
||||
.py: &py
|
||||
image: "domaindrivenarchitecture/ddadevops-python:4.10.7"
|
||||
before_script:
|
||||
- export RELEASE_ARTIFACT_TOKEN=$MEISSA_REPO_BUERO_RW
|
||||
before_script:
|
||||
- python --version
|
||||
- python -m pip install --upgrade pip
|
||||
- pip install -r requirements.txt
|
||||
|
||||
.img: &img
|
||||
image: "domaindrivenarchitecture/ddadevops-dind:4.10.7"
|
||||
services:
|
||||
- docker:dind
|
||||
before_script:
|
||||
- export IMAGE_TAG=$CI_IMAGE_TAG
|
||||
- export IMAGE_DOCKERHUB_USER=$DOCKERHUB_USER
|
||||
- export IMAGE_DOCKERHUB_PASSWORD=$DOCKERHUB_PASSWORD
|
||||
- export IMAGE_TAG=$CI_COMMIT_TAG
|
||||
|
||||
.tag_only: &tag_only
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
when: never
|
||||
- if: '$CI_COMMIT_TAG =~ /^[0-9]+\.[0-9]+\.[0-9]+$/'
|
||||
stages:
|
||||
- image
|
||||
|
||||
lint:
|
||||
<<: *py
|
||||
stage: lint&test
|
||||
script:
|
||||
- pip install -r dev_requirements.txt
|
||||
- pyb lint
|
||||
|
||||
pytest:
|
||||
<<: *py
|
||||
stage: lint&test
|
||||
script:
|
||||
- pip install -r dev_requirements.txt
|
||||
- pyb test
|
||||
|
||||
pypi-stable:
|
||||
<<: *py
|
||||
<<: *tag_only
|
||||
stage: upload
|
||||
script:
|
||||
- pyb -P version=$CI_COMMIT_TAG publish upload publish_artifacts
|
||||
|
||||
clj-cljs-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
devops-build-image-test-publish:
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/clj-cljs && pyb image publish
|
||||
|
||||
clj-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/clj && pyb image publish
|
||||
|
||||
python-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/python && pyb image publish
|
||||
|
||||
dind-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/dind && pyb image publish
|
||||
|
||||
ddadevops-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/ddadevops && pyb image publish
|
||||
|
||||
kotlin-image-publish:
|
||||
<<: *img
|
||||
<<: *tag_only
|
||||
stage: image
|
||||
script:
|
||||
- cd infrastructure/kotlin && pyb image publish
|
||||
- cd infrastructure/devops-build && pyb image
|
||||
|
|
52
README.md
52
README.md
|
@ -1,7 +1,8 @@
|
|||
# dda-devops-build
|
||||
|
||||
[![Slack](https://img.shields.io/badge/chat-clojurians-green.svg?style=flat)](https://clojurians.slack.com/messages/#dda-pallet/) | [<img src="https://domaindrivenarchitecture.org/img/delta-chat.svg" width=20 alt="DeltaChat"> chat over e-mail](mailto:buero@meissa-gmbh.de?subject=community-chat) | [<img src="https://meissa.de/images/parts/contact/mastodon36_hue9b2464f10b18e134322af482b9c915e_5501_filter_14705073121015236177.png" width=20 alt="M"> meissa@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@meissa) | [Blog](https://domaindrivenarchitecture.org) | [Website](https://meissa.de)
|
||||
[![Slack](https://img.shields.io/badge/chat-clojurians-green.svg?style=flat)](https://clojurians.slack.com/messages/#dda-pallet/) | [<img src="https://meissa-gmbh.de/img/community/Mastodon_Logotype.svg" width=20 alt="team@social.meissa-gmbh.de"> team@social.meissa-gmbh.de](https://social.meissa-gmbh.de/@team) | [Website & Blog](https://domaindrivenarchitecture.org)
|
||||
|
||||
![release prod](https://github.com/DomainDrivenArchitecture/dda-devops-build/workflows/release%20prod/badge.svg)
|
||||
|
||||
dda-devops-build integrates all the tools we use to work with clouds & provide some nice functions around.
|
||||
|
||||
|
@ -69,12 +70,12 @@ classDiagram
|
|||
DevopsBuild <|-- ProvsK3sBuild
|
||||
DevopsBuild <|-- C4kBuild
|
||||
|
||||
link DevopsBuild "dda-devops-build/src/doc/DevopsBuild.md"
|
||||
link DevopsImageBuild "dda-devops-build/src/doc/DevopsImageBuild.md"
|
||||
link DevopsTerraformBuild "dda-devops-build/src/doc/DevopsTerraformBuild.md"
|
||||
link ReleaseMixin "dda-devops-build/src/doc/ReleaseMixin.md"
|
||||
link ProvsK3sBuild "dda-devops-build/src/doc/ProvsK3sBuild.md"
|
||||
link C4kBuild "dda-devops-build/src/doc/C4kBuild.md"
|
||||
link DevopsBuild "./doc/DevopsBuild.md"
|
||||
link DevopsImageBuild "./doc/DevopsImageBuild.md"
|
||||
link DevopsTerraformBuild "./doc/DevopsTerraformBuild.md"
|
||||
link ReleaseMixin "./doc/ReleaseMixin.md"
|
||||
link ProvsK3sBuild "doc/ProvsK3sBuild.md"
|
||||
link C4kBuild "doc/C4kBuild.md"
|
||||
|
||||
```
|
||||
|
||||
|
@ -83,10 +84,6 @@ Principles we follow are:
|
|||
* Seperate build artefacts from version controlled code
|
||||
* Domain Driven Design - in order to stay sustainable
|
||||
|
||||
## Example Project
|
||||
|
||||
An example project which is using dda-devops-build can be found at: https://repo.prod.meissa.de/meissa/buildtest
|
||||
|
||||
## Installation
|
||||
|
||||
Ensure that yout python3 version is at least Python 3.10
|
||||
|
@ -97,9 +94,17 @@ pip3 install -r requirements.txt
|
|||
export PATH=$PATH:~/.local/bin
|
||||
```
|
||||
|
||||
## Example Project
|
||||
## Reference
|
||||
|
||||
An example project which is using dda-devops-build can be found at: https://repo.prod.meissa.de/meissa/buildtest
|
||||
* [DevopsBuild](./doc/DevopsBuild.md)
|
||||
* [DevopsImageBuild](./doc/DevopsImageBuild.md)
|
||||
* [DevopsTerraformBuild](./doc/DevopsTerraformBuild.md)
|
||||
* [AwsProvider](doc/DevopsTerraformBuildWithAwsProvider.md)
|
||||
* [DigitaloceanProvider](doc/DevopsTerraformBuildWithDigitaloceanProvider.md)
|
||||
* [HetznerProvider](doc/DevopsTerraformBuildWithHetznerProvider.md)
|
||||
* [ReleaseMixin](./doc/ReleaseMixin.md)
|
||||
* [ProvsK3sBuild](doc/ProvsK3sBuild.md)
|
||||
* [C4kBuild](doc/C4kBuild.md)
|
||||
|
||||
## Example Build
|
||||
|
||||
|
@ -181,23 +186,10 @@ def destroy(project):
|
|||
pyb dev publish upload
|
||||
pip3 install --upgrade ddadevops --pre
|
||||
|
||||
pyb [patch|minor|major]
|
||||
pyb [patch|minor|major] prepare_release tag_bump_and_push_release
|
||||
pip3 install --upgrade ddadevops
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
* [DevopsBuild](./doc/DevopsBuild.md)
|
||||
* [DevopsImageBuild](./doc/DevopsImageBuild.md)
|
||||
* [DevopsTerraformBuild](./doc/DevopsTerraformBuild.md)
|
||||
* [AwsProvider](doc/DevopsTerraformBuildWithAwsProvider.md)
|
||||
* [DigitaloceanProvider](doc/DevopsTerraformBuildWithDigitaloceanProvider.md)
|
||||
* [HetznerProvider](doc/DevopsTerraformBuildWithHetznerProvider.md)
|
||||
* [ReleaseMixin](./doc/ReleaseMixin.md)
|
||||
* [ProvsK3sBuild](doc/ProvsK3sBuild.md)
|
||||
* [C4kBuild](doc/C4kBuild.md)
|
||||
|
||||
|
||||
## Development & mirrors
|
||||
|
||||
Development happens at: https://repo.prod.meissa.de/meissa/dda-devops-build
|
||||
|
@ -205,7 +197,6 @@ Development happens at: https://repo.prod.meissa.de/meissa/dda-devops-build
|
|||
Mirrors are:
|
||||
|
||||
* https://gitlab.com/domaindrivenarchitecture/dda-devops-build (issues and PR, CI)
|
||||
* https://github.com/DomainDrivenArchitecture/dda-devops-build
|
||||
|
||||
For more details about our repository model see: https://repo.prod.meissa.de/meissa/federate-your-repos
|
||||
|
||||
|
@ -213,3 +204,8 @@ For more details about our repository model see: https://repo.prod.meissa.de/mei
|
|||
|
||||
Copyright © 2021 meissa GmbH
|
||||
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
||||
|
||||
## License
|
||||
|
||||
Copyright © 2023 meissa GmbH
|
||||
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
||||
|
|
142
build.py
142
build.py
|
@ -22,18 +22,18 @@ from ddadevops import *
|
|||
use_plugin("python.core")
|
||||
use_plugin("copy_resources")
|
||||
use_plugin("filter_resources")
|
||||
# use_plugin("python.unittest")
|
||||
# use_plugin("python.coverage")
|
||||
#use_plugin("python.unittest")
|
||||
#use_plugin("python.coverage")
|
||||
use_plugin("python.distutils")
|
||||
|
||||
# use_plugin("python.install_dependencies")
|
||||
#use_plugin("python.install_dependencies")
|
||||
|
||||
default_task = "dev"
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "not-used"
|
||||
PROJECT_ROOT_PATH = "."
|
||||
version = "4.13.2-dev"
|
||||
version = "4.0.12-dev"
|
||||
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
|
||||
description = __doc__
|
||||
authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")]
|
||||
|
@ -41,52 +41,44 @@ url = "https://repo.prod.meissa.de/meissa/dda-devops-build"
|
|||
requires_python = ">=3.10" # CHECK IF NEW VERSION EXISTS
|
||||
license = "Apache Software License"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
# project.build_depends_on('mockito')
|
||||
# project.build_depends_on('unittest-xml-reporting')
|
||||
project.build_depends_on("ddadevops>=4.7.0")
|
||||
#project.build_depends_on('mockito')
|
||||
#project.build_depends_on('unittest-xml-reporting')
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
||||
|
||||
project.set_property("verbose", True)
|
||||
project.get_property("filter_resources_glob").append(
|
||||
"main/python/ddadevops/__init__.py"
|
||||
)
|
||||
project.get_property("filter_resources_glob").append("main/python/ddadevops/__init__.py")
|
||||
project.set_property("dir_source_unittest_python", "src/test/python")
|
||||
|
||||
project.set_property("copy_resources_target", "$dir_dist/ddadevops")
|
||||
project.get_property("copy_resources_glob").append("LICENSE")
|
||||
project.get_property("copy_resources_glob").append("src/main/resources/terraform/*")
|
||||
project.get_property("copy_resources_glob").append(
|
||||
"src/main/resources/docker/image/resources/*"
|
||||
)
|
||||
project.get_property("copy_resources_glob").append("src/main/resources/docker/image/resources/*")
|
||||
project.include_file("ddadevops", "LICENSE")
|
||||
project.include_file("ddadevops", "src/main/resources/terraform/*")
|
||||
project.include_file("ddadevops", "src/main/resources/docker/image/resources/*")
|
||||
|
||||
# project.set_property('distutils_upload_sign', True)
|
||||
# project.set_property('distutils_upload_sign_identity', '')
|
||||
#project.set_property('distutils_upload_sign', True)
|
||||
#project.set_property('distutils_upload_sign_identity', '')
|
||||
project.set_property("distutils_readme_description", True)
|
||||
project.set_property("distutils_description_overwrite", True)
|
||||
project.set_property(
|
||||
"distutils_classifiers",
|
||||
[
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: OS Independent",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
"Topic :: Software Development :: Build Tools",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
"Topic :: Software Development :: Testing",
|
||||
],
|
||||
)
|
||||
project.set_property("distutils_classifiers", [
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Operating System :: OS Independent',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Topic :: Software Development :: Build Tools',
|
||||
'Topic :: Software Development :: Quality Assurance',
|
||||
'Topic :: Software Development :: Testing'
|
||||
])
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
|
@ -96,99 +88,59 @@ def initialize(project):
|
|||
"build_types": [],
|
||||
"mixin_types": ["RELEASE"],
|
||||
"release_primary_build_file": "build.py",
|
||||
"release_secondary_build_files": [
|
||||
"infrastructure/python/build.py",
|
||||
"infrastructure/dind/build.py",
|
||||
"infrastructure/ddadevops/build.py",
|
||||
"infrastructure/clj-cljs/build.py",
|
||||
"infrastructure/clj/build.py",
|
||||
"infrastructure/kotlin/build.py",
|
||||
],
|
||||
"release_artifacts": [],
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": "meissa",
|
||||
"release_repository_name": "dda-devops-build",
|
||||
}
|
||||
|
||||
build = ReleaseMixin(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
run("pytest", check=True)
|
||||
|
||||
|
||||
@task
|
||||
def lint(project):
|
||||
run(
|
||||
"flake8 --max-line-length=120 --count --select=E9,F63,F7,F82 "
|
||||
+ "--show-source --statistics src/main/python/ddadevops/",
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
run(
|
||||
"flake8 --count --exit-zero --max-complexity=10 --max-line-length=127 "
|
||||
+ '--per-file-ignores="__init__.py:F401" '
|
||||
+ "--ignore=E722,W503 --statistics src/main/python/ddadevops/",
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
run(
|
||||
"python -m mypy src/main/python/ddadevops/ --ignore-missing-imports "
|
||||
+ "--disable-error-code=attr-defined --disable-error-code=union-attr",
|
||||
shell=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
run("flake8 --max-line-length=120 --count --select=E9,F63,F7,F82 "+
|
||||
"--show-source --statistics src/main/python/ddadevops/", shell=True, check=True)
|
||||
run("flake8 --count --exit-zero --max-complexity=10 --max-line-length=127 "+
|
||||
"--per-file-ignores=\"__init__.py:F401\" "+
|
||||
"--ignore=E722,W503 --statistics src/main/python/ddadevops/", shell=True, check=True)
|
||||
run("python -m mypy src/main/python/ddadevops/ --ignore-missing-imports "+
|
||||
"--disable-error-code=attr-defined --disable-error-code=union-attr", shell=True, check=True)
|
||||
run("pylint -d W0511,R0903,C0301,W0614,C0114,C0115,C0116,similarities,W1203,W0702,W0702,"+
|
||||
"R0913,R0902,R0914,R1732,R1705,W0707,C0123,W0703,C0103 src/main/python/ddadevops/", shell=True, check=True)
|
||||
|
||||
@task
|
||||
def patch(project):
|
||||
linttest(project, "PATCH")
|
||||
release(project)
|
||||
|
||||
build(project, "PATCH")
|
||||
|
||||
@task
|
||||
def minor(project):
|
||||
linttest(project, "MINOR")
|
||||
release(project)
|
||||
|
||||
build(project, "MINOR")
|
||||
|
||||
@task
|
||||
def major(project):
|
||||
linttest(project, "MAJOR")
|
||||
release(project)
|
||||
|
||||
build(project, "MAJOR")
|
||||
|
||||
@task
|
||||
def dev(project):
|
||||
linttest(project, "NONE")
|
||||
|
||||
build(project, "NONE")
|
||||
|
||||
@task
|
||||
def prepare(project):
|
||||
def nothing(project):
|
||||
pass
|
||||
|
||||
@task
|
||||
def prepare_release(project):
|
||||
build = get_devops_build(project)
|
||||
build.prepare_release()
|
||||
|
||||
|
||||
@task
|
||||
def tag(project):
|
||||
def tag_bump_and_push_release(project):
|
||||
build = get_devops_build(project)
|
||||
build.tag_bump_and_push_release()
|
||||
|
||||
|
||||
@task
|
||||
def publish_artifacts(project):
|
||||
build = get_devops_build(project)
|
||||
build.publish_artifacts()
|
||||
|
||||
|
||||
def release(project):
|
||||
prepare(project)
|
||||
tag(project)
|
||||
|
||||
|
||||
def linttest(project, release_type):
|
||||
def build(project, release_type):
|
||||
build = get_devops_build(project)
|
||||
build.update_release_type(release_type)
|
||||
test(project)
|
||||
|
|
|
@ -35,12 +35,7 @@ classDiagram
|
|||
| name | name in context of build & ENV | - | |
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Example project
|
||||
|
||||
A complete example project you can find on: https://repo.prod.meissa.de/meissa/buildtest
|
||||
|
||||
### Example of a build.py
|
||||
### build.py
|
||||
|
||||
```python
|
||||
from os import environ
|
||||
|
|
|
@ -23,9 +23,12 @@ classDiagram
|
|||
| build_dir_name | name of dir, build is executed in | target |
|
||||
| build_types | list of special builds used. Valid values are ["IMAGE", "C4K", "K3S", "TERRAFORM"] | [] |
|
||||
| mixin_types | mixins are orthoganl to builds and represent additional capabilities. Valid Values are ["RELEASE"] | [] |
|
||||
| module | module name - may result in a hierarchy like name/module | |
|
||||
| name | dedicated name of the build | module |
|
||||
| project_root_path | relative path to projects root. Is used to locate the target dir | |
|
||||
| stage | sth. like test, int, acc or prod | |
|
||||
|
||||
## Example Usage
|
||||
|
||||
### build.py
|
||||
|
||||
```python
|
||||
|
|
|
@ -30,7 +30,7 @@ classDiagram
|
|||
| image_dockerhub_user | user to access docker-hub | IMAGE_DOCKERHUB_USER from env or credentials from gopass |
|
||||
| image_dockerhub_password | password to access docker-hub | IMAGE_DOCKERHUB_PASSWORD from env or credentials from gopass |
|
||||
| image_tag | tag for publishing the image | IMAGE_TAG from env |
|
||||
| image_naming | Strategy for calculate the image name. Posible values are [NAME_ONLY,NAME_AND_MODULE] |NAME_ONLY |
|
||||
|
||||
|
||||
### Credentials Mapping defaults
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
# ddadevops Images
|
||||
## ddadevops-clojure
|
||||
|
||||
Contains
|
||||
* clojure
|
||||
* shadowcljs
|
||||
* lein
|
||||
* java
|
||||
* graalvm
|
||||
* pybuilder, ddadevops
|
||||
|
||||
## ddadevops
|
||||
|
||||
Contains:
|
||||
* pybuilder, ddadevops
|
||||
|
||||
## devops-build
|
||||
|
||||
Image is deprecated.
|
||||
|
||||
## ddadevops-dind
|
||||
|
||||
Contains:
|
||||
* docker in docker
|
||||
* pybuilder, ddadevops
|
||||
|
||||
## ddadevops-python
|
||||
|
||||
Contains:
|
||||
* python 3.10
|
||||
* python linting
|
||||
* python setup-tools
|
||||
* pybuilder, ddadevops
|
|
@ -14,16 +14,13 @@ classDiagram
|
|||
## Input
|
||||
|
||||
| name | description | default |
|
||||
| --------------------------------- | ----------------------------------------------------------------- | --------- |
|
||||
| ----------------------------- | ----------------------------------------------------------------- | --------- |
|
||||
| k3s_provision_user | the user used to provision k3s | "root" |
|
||||
| k3s_letsencrypt_email | email address used for letsencrypt | |
|
||||
| k3s_letsencrypt_endpoint | letsencrypt endpoint. Valid values are staging, prod | "staging" |
|
||||
| k3s_app_filename_to_provision | an k8s manifest to apply imediately after k3s setup was sucessful | |
|
||||
| k3s_enable_echo | provision the echo app on k3s. Valid values are true, false | "false" |
|
||||
| k3s_provs_template | use a individual template for provs config | None |
|
||||
| k3s_enable_hetzner_csi | enable hetzner csi | False |
|
||||
| k3s_hetzner_api_token | hetzner_api_token | None |
|
||||
| k3s_hetzner_encryption_passphrase | encryption passphrase for volumes | None |
|
||||
|
||||
### Credentials Mapping defaults
|
||||
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
# ReleaseMixin
|
||||
|
||||
- [ReleaseMixin](#releasemixin)
|
||||
- [Input](#input)
|
||||
- [Example Usage just for creating releases](#example-usage-just-for-creating-releases)
|
||||
- [build.py](#buildpy)
|
||||
- [call the build for creating a major release](#call-the-build-for-creating-a-major-release)
|
||||
- [Example Usage for creating a release on forgejo / gitea \& upload the generated artifacts](#example-usage-for-creating-a-release-on-forgejo--gitea--upload-the-generated-artifacts)
|
||||
- [build.py](#buildpy-1)
|
||||
- [call the build](#call-the-build)
|
||||
|
||||
|
||||
Support for releases following the trunk-based-release flow (see https://trunkbaseddevelopment.com/)
|
||||
|
||||
```mermaid
|
||||
|
@ -18,7 +8,6 @@ classDiagram
|
|||
prepare_release() - adjust all build files to carry the correct version & commit locally
|
||||
tag_and_push_release() - tag the git repo and push changes to origin
|
||||
update_release_type (release_type) - change the release type during run time
|
||||
publish_artifacts() - publish release & artifacts to forgejo/gitea
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -26,103 +15,13 @@ classDiagram
|
|||
## Input
|
||||
|
||||
| name | description | default |
|
||||
| ----------------------------- |-----------------------------------------------------------------------------------------------------------------------| --------------- |
|
||||
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------- |
|
||||
| release_type | one of MAJOR, MINOR, PATCH, NONE | "NONE" |
|
||||
| release_main_branch | the name of your trunk | "main" |
|
||||
| release_main_branch | the name of your trank | "main" |
|
||||
| release_primary_build_file | path to the build file having the leading version info (read & write). Valid extensions are .clj, .json, .gradle, .py | "./project.clj" |
|
||||
| release_secondary_build_files | list of secondary build files, version is written in. | [] |
|
||||
| release_artifact_server_url | Optional: The base url of your forgejo/gitea instance to publish a release tode | |
|
||||
| release_organisation | Optional: The repository organisation name | |
|
||||
| release_repository_name | Optional: The repository name name | |
|
||||
| release_artifacts | Optional: The list of artifacts to publish to the release generated name | [] |
|
||||
| release_tag_prefix | Optional: Prefix of tag | "" |
|
||||
|
||||
## Example Usage just for creating releases
|
||||
|
||||
### build.py
|
||||
|
||||
```python
|
||||
from os import environ
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = 'my-project'
|
||||
MODULE = 'my-module'
|
||||
PROJECT_ROOT_PATH = '..'
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
project.build_depends_on("ddadevops>=4.7.0")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": [],
|
||||
"mixin_types": ["RELEASE"],
|
||||
"release_type": "MINOR",
|
||||
"release_primary_build_file": "project.clj",
|
||||
"release_secondary_build_files": ["package.json"],
|
||||
}
|
||||
build = ReleaseMixin(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def patch(project):
|
||||
linttest(project, "PATCH")
|
||||
release(project)
|
||||
|
||||
|
||||
@task
|
||||
def minor(project):
|
||||
linttest(project, "MINOR")
|
||||
release(project)
|
||||
|
||||
|
||||
@task
|
||||
def major(project):
|
||||
linttest(project, "MAJOR")
|
||||
release(project)
|
||||
|
||||
|
||||
@task
|
||||
def dev(project):
|
||||
linttest(project, "NONE")
|
||||
|
||||
|
||||
@task
|
||||
def prepare(project):
|
||||
build = get_devops_build(project)
|
||||
build.prepare_release()
|
||||
|
||||
|
||||
@task
|
||||
def tag(project):
|
||||
build = get_devops_build(project)
|
||||
build.tag_bump_and_push_release()
|
||||
|
||||
|
||||
def release(project):
|
||||
prepare(project)
|
||||
tag(project)
|
||||
|
||||
|
||||
def linttest(project, release_type):
|
||||
build = get_devops_build(project)
|
||||
build.update_release_type(release_type)
|
||||
#test(project)
|
||||
#lint(project)
|
||||
```
|
||||
|
||||
### call the build for creating a major release
|
||||
|
||||
```bash
|
||||
pyb major
|
||||
```
|
||||
|
||||
## Example Usage for creating a release on forgejo / gitea & upload the generated artifacts
|
||||
## Example Usage
|
||||
|
||||
### build.py
|
||||
|
||||
|
@ -137,7 +36,7 @@ PROJECT_ROOT_PATH = '..'
|
|||
|
||||
@init
|
||||
def initialize(project):
|
||||
project.build_depends_on("ddadevops>=4.7.0")
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
|
@ -149,23 +48,35 @@ def initialize(project):
|
|||
"release_type": "MINOR",
|
||||
"release_primary_build_file": "project.clj",
|
||||
"release_secondary_build_files": ["package.json"],
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": "meissa",
|
||||
"release_repository_name": "dda-devops-build",
|
||||
"release_artifacts": ["target/doc.zip"],
|
||||
}
|
||||
|
||||
roject.build_depends_on("ddadevops>=4.0.0-dev")
|
||||
|
||||
build = ReleaseMixin(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def publish_artifacts(project):
|
||||
def prepare_release(project):
|
||||
build = get_devops_build(project)
|
||||
build.publish_artifacts()
|
||||
build.prepare_release()
|
||||
|
||||
@task
|
||||
def build(project):
|
||||
print("do the build")
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
print("publish your artefacts")
|
||||
|
||||
@task
|
||||
def after_publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.tag_bump_and_push_release()
|
||||
```
|
||||
|
||||
### call the build
|
||||
|
||||
```bash
|
||||
git checkout "4.7.0"
|
||||
pyb publish_artifacts
|
||||
pyb prepare_release build publish after_publish
|
||||
```
|
||||
|
|
|
@ -12,7 +12,6 @@ classDiagram
|
|||
}
|
||||
|
||||
class Image {
|
||||
image_naming
|
||||
image_dockerhub_user
|
||||
image_dockerhub_password
|
||||
image_publish_tag
|
||||
|
@ -88,15 +87,6 @@ classDiagram
|
|||
release_type
|
||||
release_main_branch
|
||||
release_current_branch
|
||||
release_artifact_server_url
|
||||
release_organisation
|
||||
release_repository_name
|
||||
release_artifact_token
|
||||
}
|
||||
class Artifact {
|
||||
path_str
|
||||
path()
|
||||
type()
|
||||
}
|
||||
class Credentials {
|
||||
<<AggregateRoot>>
|
||||
|
@ -139,7 +129,6 @@ classDiagram
|
|||
TerraformDomain *-- "0..1" ProviderAws: providers
|
||||
Release o-- "0..1" BuildFile: primary_build_file
|
||||
Release o-- "0..n" BuildFile: secondary_build_files
|
||||
Release "1" *-- "0..n" Artifact: release_artifacts
|
||||
Release "1" *-- "1" Version: version
|
||||
BuildFile *-- "1" Version: version
|
||||
C4k *-- DnsRecord: dns_record
|
||||
|
|
|
@ -16,85 +16,35 @@ We discussed how we will handle releases in cooperation with gitlab-ci.
|
|||
|
||||
### Outcome of Eventstroming: Events ordered by time
|
||||
|
||||
* B: is the human devops
|
||||
* S: is the build / ci system
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
state prepare_release {
|
||||
state "B: Pulls the latest changes" as pull
|
||||
state "B: Possibly merge/rebase with main" as merge
|
||||
state "B: starts 'create release-notes'" as rn
|
||||
state "B: commits his changes with [skip-ci]." as c1
|
||||
|
||||
[*] --> pull
|
||||
pull --> merge
|
||||
merge --> rn
|
||||
rn --> c1
|
||||
c1 --> [*]
|
||||
}
|
||||
state release {
|
||||
state "B: starts the release build and specifies major, minor, patch" as trigger
|
||||
state "S: does a git fetch & status and checks if there are no changes at origin" as fetch
|
||||
state "S: starts tests" as test
|
||||
state "S: runs the linting" as lint
|
||||
state "S: possibly does image building and image testing" as image
|
||||
state "S: version numbers are adjusted in project.clj/package.json to full version" as vno
|
||||
state "S: change commit is tagged with git tag" as c2
|
||||
state "S: version numbers are adjusted in project.clj/package.json to next snapshot " as snap
|
||||
state "S: makes a bump commit with [skip-ci]." as c3
|
||||
state "S: push to gitlab/gitea along with git tags" as push
|
||||
|
||||
[*] --> trigger
|
||||
trigger --> fetch
|
||||
fetch --> lint
|
||||
fetch --> test
|
||||
fetch --> image
|
||||
test --> vno
|
||||
lint --> vno
|
||||
image --> vno
|
||||
vno --> c2
|
||||
c2 --> snap
|
||||
snap --> c3
|
||||
c3 --> push
|
||||
push --> [*]
|
||||
}
|
||||
state ci_tag {
|
||||
state "S: CI starts - for a new tag" as ct1
|
||||
state "S: runs the linting" as ct2
|
||||
state "S: CI runs tests" as ct3
|
||||
state "S: makes artifacts" as ct4
|
||||
state "S: possibly performs image building and image testing" as ct5
|
||||
state "S: publishes images and artifacts" as ct6
|
||||
|
||||
|
||||
[*] --> ct1
|
||||
ct1 --> ct2
|
||||
ct2 --> ct3
|
||||
ct3 --> ct4
|
||||
ct4 --> ct5
|
||||
ct5 --> ct6
|
||||
ct6 --> [*]
|
||||
}
|
||||
state ci_version_bump {
|
||||
state "S: CI starts - for push with the last commit" as cvb1
|
||||
state "S: CI runs tests" as cvb2
|
||||
state "S: performs the linting" as cvb3
|
||||
|
||||
[*] --> cvb1
|
||||
cvb1 --> cvb2
|
||||
cvb2 --> cvb3
|
||||
cvb3 --> [*]
|
||||
}
|
||||
|
||||
[*] --> prepare_release
|
||||
prepare_release --> release
|
||||
release --> ci_tag
|
||||
release --> ci_version_bump
|
||||
ci_tag --> [*]
|
||||
ci_version_bump --> [*]
|
||||
|
||||
```
|
||||
1. B: Pulls the latest changes
|
||||
1. B: Possibly merge/rebase with main
|
||||
1.
|
||||
1. B: starts "create release-notes"
|
||||
1. B: commits his changes with [skip-ci].
|
||||
1.
|
||||
1. B: starts the release build and specifies major, minor, patch
|
||||
1.
|
||||
1. S: does a git fetch & status and checks if there are no changes at origin
|
||||
1. S: starts tests
|
||||
1. S: runs the linting
|
||||
1. S: possibly does image building and image testing
|
||||
1.
|
||||
1. S: version numbers are adjusted in project.clj/package.json to full version
|
||||
1. S: change commit is tagged with git tag
|
||||
1. S: version numbers are adjusted in project.clj/package.json to next snapshot version
|
||||
1. S: makes a bump commit with [skip-ci].
|
||||
1. S: push to gitlab/gitea along with git tags
|
||||
1.
|
||||
1. S: CI starts - for a new tag
|
||||
1. S: CI runs tests
|
||||
1. S: runs the linting
|
||||
1. S: makes artifacts
|
||||
1. S: possibly performs image building and image testing
|
||||
1. S: publishes images and artifacts
|
||||
1.
|
||||
1. S: CI starts - for push with the last commit
|
||||
1. S: CI runs tests
|
||||
1. S: performs the linting
|
||||
|
||||
## Consequences
|
||||
|
||||
|
|
8
doc/dev/releasing.md
Normal file
8
doc/dev/releasing.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
adjust version no in build.py to release version no.
|
||||
git commit -am "release"
|
||||
git tag -am "release" [release version no]
|
||||
git push --follow-tags
|
||||
increase version no in build.py
|
||||
git commit -am "version bump"
|
||||
git push
|
||||
pip3 install --upgrade ddadevops
|
|
@ -1,56 +0,0 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
import logging
|
||||
|
||||
name = 'dda-backup'
|
||||
MODULE = 'NOT_SET'
|
||||
PROJECT_ROOT_PATH = '../..'
|
||||
version = "4.12.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_ONLY",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.7.0")
|
||||
|
||||
build = DevopsImageBuild(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def image(project):
|
||||
build = get_devops_build(project)
|
||||
build.image()
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
build = get_devops_build(project)
|
||||
build.test()
|
||||
|
||||
@task
|
||||
def drun(project):
|
||||
build = get_devops_build(project)
|
||||
build.drun()
|
||||
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.dockerhub_login()
|
||||
build.dockerhub_publish()
|
|
@ -1,79 +0,0 @@
|
|||
## Init Statemachine
|
||||
|
||||
### Inputs
|
||||
1. `restic-password: ""`
|
||||
2. `restic-password-to-rotate: ""`
|
||||
|
||||
### Manual init the restic repository for the first time
|
||||
|
||||
1. apply backup-and-restore pod:
|
||||
`kubectl scale deployment backup-restore --replicas=1`
|
||||
2. exec into pod and execute restore pod (press tab to get your exact pod name)
|
||||
`kubectl exec -it backup-restore-... -- /usr/local/bin/init.sh`
|
||||
3. remove backup-and-restore pod:
|
||||
`kubectl scale deployment backup-restore --replicas=0`
|
||||
|
||||
### Password Rotation
|
||||
|
||||
1. apply backup-and-restore pod:
|
||||
`kubectl scale deployment backup-restore --replicas=1`
|
||||
2. add new password to restic repository
|
||||
`restic key add ....`
|
||||
=> Trigger ::
|
||||
field (1) credential current
|
||||
filed (2) credential new
|
||||
3. replace field (1) with (2) & clear (2)
|
||||
4. remove old key - ???
|
||||
`restic remove ....`
|
||||
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> init
|
||||
init --> backup_ready: trigger, restic-password !empty
|
||||
backup_ready --> new_password_added: restic-password !empty && restic-password-to-rotate !empty
|
||||
new_password_added --> backup_ready: restic-password !empty && restic-password-to-rotate empty
|
||||
```
|
||||
|
||||
### First Steps
|
||||
|
||||
1. Cloud Testserver hochfahren
|
||||
2. Dort backup-restore deployment (leeres Secret mgl.?), neues Secret "rotation-credential-secret" als Daten
|
||||
3. mounten von angelegtem Secret in Pod backup-restore
|
||||
4. ba*bash*ka Skript in pod starten -> liest Secret ?leer
|
||||
5. Micha cons.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant k8s
|
||||
participant e as entrypoint.sh
|
||||
participant rm as restic-management.clj
|
||||
|
||||
k8s ->> e: cronjob calls
|
||||
e ->> rm: start-file
|
||||
rm ->> rm: rotate
|
||||
activate rm
|
||||
rm ->> rm: read-backup-repository-state (state)
|
||||
rm ->> rm: read-secret (backup-secret/restic-password, rotation-credential-secret/rotation-credential)
|
||||
rm ->> rm: switch
|
||||
activate rm
|
||||
rm ->> rm: if init && restic-password != null
|
||||
activate rm
|
||||
rm ->> rm: init.sh
|
||||
rm ->> rm: state init -> backup-ready
|
||||
deactivate rm
|
||||
rm ->> rm: if backup-ready && rotation-credential != null
|
||||
activate rm
|
||||
rm ->> rm: add-new-password-to-restic-repository.sh
|
||||
rm ->> rm: state backup-ready -> new-password-added
|
||||
deactivate rm
|
||||
rm ->> rm: if new-password-added && rotation-credential == null
|
||||
activate rm
|
||||
rm ->> rm: remove-old-password-from-restic-repository.sh
|
||||
rm ->> rm: state new-password-added -> backup-ready
|
||||
deactivate rm
|
||||
deactivate rm
|
||||
|
||||
rm ->> rm: store-repository-state (state)
|
||||
deactivate rm
|
||||
```
|
|
@ -1,5 +0,0 @@
|
|||
FROM ubuntu:jammy
|
||||
|
||||
# install it
|
||||
ADD resources /tmp/
|
||||
RUN /tmp/install.sh
|
|
@ -1,70 +0,0 @@
|
|||
backup_file_path='files'
|
||||
|
||||
function init-file-repo() {
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_file_path} -v init
|
||||
else
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_file_path} -v init --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
# First arg is the directory, second is optional for the path to a certificate file
|
||||
function backup-directory() {
|
||||
local directory="$1"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache
|
||||
cd ${directory} && restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} backup .
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune
|
||||
else
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache --cacert ${CERTIFICATE_FILE}
|
||||
cd ${directory} && restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} backup . --cacert ${CERTIFICATE_FILE}
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
# First arg is the directory, the remaining args are the sub-directories (relative to the first directory) to backup.
|
||||
function backup-fs-from-directory() {
|
||||
local directory="$1"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache
|
||||
cd ${directory} && restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} backup $@
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune
|
||||
else
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache --cacert ${CERTIFICATE_FILE}
|
||||
cd ${directory} && restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} backup $@ --cacert ${CERTIFICATE_FILE}
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Das tut so nicht!
|
||||
function restore-directory() {
|
||||
local directory="$1"; shift
|
||||
local snapshot_id="${1:-latest}"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache
|
||||
rm -rf ${directory}*
|
||||
restic -v -r $RESTIC_REPOSITORY/${backup_file_path} restore ${snapshot_id} --target ${directory}
|
||||
else
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_file_path} unlock --cleanup-cache --cacert ${CERTIFICATE_FILE}
|
||||
rm -rf ${directory}*
|
||||
restic -v -r $RESTIC_REPOSITORY/${backup_file_path} restore ${snapshot_id} --target ${directory} --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function list-snapshot-files() {
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_file_path} snapshots
|
||||
else
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_file_path} snapshots --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
# usage: file_env VAR [DEFAULT]
|
||||
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
|
||||
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
|
||||
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
|
||||
function file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
local val="$def"
|
||||
if [ "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ "${!fileVar:-}" ]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
export "$var"="$val"
|
||||
unset "$fileVar"
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
function babashka_install() {
|
||||
babashka_version="1.3.189"
|
||||
curl -SsLo /tmp/babashka-${babashka_version}-linux-amd64.tar.gz https://github.com/babashka/babashka/releases/download/v${babashka_version}/babashka-${babashka_version}-linux-amd64.tar.gz
|
||||
curl -SsLo /tmp/checksum https://github.com/babashka/babashka/releases/download/v${babashka_version}/babashka-${babashka_version}-linux-amd64.tar.gz.sha256
|
||||
echo " /tmp/babashka-$babashka_version-linux-amd64.tar.gz"|tee -a /tmp/checksum
|
||||
sha256sum -c --status /tmp/checksum
|
||||
tar -C /tmp -xzf /tmp/babashka-${babashka_version}-linux-amd64.tar.gz
|
||||
install -m 0700 -o root -g root /tmp/bb /usr/local/bin/
|
||||
}
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
apt-get install -qqy ca-certificates curl gnupg postgresql-client-14 restic
|
||||
curl -Ss --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg
|
||||
sh -c 'echo "deb [signed-by=/etc/apt/trusted.gpg.d/postgresql-common_pgdg_archive_keyring.gpg] https://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
upgradeSystem
|
||||
babashka_install
|
||||
} > /dev/null
|
||||
|
||||
update-ca-certificates
|
||||
|
||||
install -m 0400 /tmp/functions.sh /usr/local/lib/
|
||||
install -m 0400 /tmp/pg-functions.sh /usr/local/lib/
|
||||
install -m 0400 /tmp/file-functions.sh /usr/local/lib/
|
||||
install -m 0740 /tmp/restic_management.clj /usr/local/bin/
|
||||
|
||||
cleanupDocker
|
||||
}
|
||||
|
||||
source /tmp/install_functions_debian.sh
|
||||
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
|
@ -1,149 +0,0 @@
|
|||
backup_pg_role_path='pg-role'
|
||||
backup_pg_database_path='pg-database'
|
||||
|
||||
function init-command() {
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} -v init $@
|
||||
}
|
||||
|
||||
function init-role-repo() {
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
init-command
|
||||
else
|
||||
init-command --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
function init-database-command() {
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} -v init $@
|
||||
}
|
||||
|
||||
function init-database-repo() {
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
init-database-command
|
||||
else
|
||||
init-database-command --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
function drop-create-db() {
|
||||
psql -d template1 -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password -c "DROP DATABASE \"${POSTGRES_DB}\";"
|
||||
psql -d template1 -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password -c "CREATE DATABASE \"${POSTGRES_DB}\";"
|
||||
}
|
||||
|
||||
function create-pg-pass() {
|
||||
local pg_host=${POSTGRES_HOST:-localhost}
|
||||
|
||||
echo "${pg_host}:${POSTGRES_DB}:${POSTGRES_USER}:${POSTGRES_PASSWORD}" > /root/.pgpass
|
||||
echo "${POSTGRES_HOST}:template1:${POSTGRES_USER}:${POSTGRES_PASSWORD}" >> /root/.pgpass
|
||||
chmod 0600 /root/.pgpass
|
||||
}
|
||||
|
||||
function roles-unlock-command() {
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} unlock --cleanup-cache $@
|
||||
}
|
||||
|
||||
function roles-forget-command() {
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune $@
|
||||
}
|
||||
|
||||
function backup-roles() {
|
||||
local role_prefix="$1"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
roles-unlock-command
|
||||
pg_dumpall -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U${POSTGRES_USER} --no-password --roles-only | \
|
||||
grep ${role_prefix} | restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} backup --stdin
|
||||
roles-forget-command
|
||||
else
|
||||
roles-unlock-command --cacert ${CERTIFICATE_FILE}
|
||||
pg_dumpall -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U${POSTGRES_USER} --no-password --roles-only | \
|
||||
grep ${role_prefix} | restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} backup --stdin --cacert ${CERTIFICATE_FILE}
|
||||
roles-forget-command --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
function db-unlock-command() {
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} unlock --cleanup-cache $@
|
||||
}
|
||||
|
||||
function db-forget-command() {
|
||||
restic -v -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} forget --group-by '' --keep-last 1 --keep-daily ${RESTIC_DAYS_TO_KEEP} --keep-monthly ${RESTIC_MONTHS_TO_KEEP} --prune $@
|
||||
}
|
||||
|
||||
function backup-db-dump() {
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
db-unlock-command
|
||||
pg_dump -d ${POSTGRES_DB} -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} \
|
||||
-U ${POSTGRES_USER} --no-password --serializable-deferrable | \
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} backup --stdin
|
||||
db-forget-command
|
||||
else
|
||||
db-unlock-command --cacert ${CERTIFICATE_FILE}
|
||||
pg_dump -d ${POSTGRES_DB} -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} \
|
||||
-U ${POSTGRES_USER} --no-password --serializable-deferrable | \
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} backup --stdin --cacert ${CERTIFICATE_FILE}
|
||||
db-forget-command --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
function restore-roles() {
|
||||
local snapshot_id="${1:-latest}"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
roles-unlock-command
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} dump ${snapshot_id} stdin | \
|
||||
psql -d template1 -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password
|
||||
else
|
||||
roles-unlock-command --cacert ${CERTIFICATE_FILE}
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} dump ${snapshot_id} stdin --cacert ${CERTIFICATE_FILE} | \
|
||||
psql -d template1 -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password
|
||||
fi
|
||||
}
|
||||
|
||||
function restore-db() {
|
||||
local snapshot_id="${1:-latest}"; shift
|
||||
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
db-unlock-command
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} dump ${snapshot_id} stdin | \
|
||||
psql -d ${POSTGRES_DB} -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password
|
||||
else
|
||||
db-unlock-command --cacert ${CERTIFICATE_FILE}
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} dump ${snapshot_id} stdin --cacert ${CERTIFICATE_FILE} | \
|
||||
psql -d ${POSTGRES_DB} -h ${POSTGRES_SERVICE} -p ${POSTGRES_PORT} -U ${POSTGRES_USER} \
|
||||
--no-password
|
||||
fi
|
||||
}
|
||||
|
||||
function list-snapshot-roles() {
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_role_path} snapshots
|
||||
else
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} snapshots --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
||||
|
||||
function list-snapshot-db() {
|
||||
if [ -z ${CERTIFICATE_FILE} ];
|
||||
then
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} snapshots
|
||||
else
|
||||
restic -r ${RESTIC_REPOSITORY}/${backup_pg_database_path} snapshots --cacert ${CERTIFICATE_FILE}
|
||||
fi
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
#! /usr/bin/env bb
|
||||
|
||||
(ns restic-management
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.edn :as edn]))
|
||||
|
||||
(s/def ::state string?)
|
||||
|
||||
(s/def ::backup-repository-state
|
||||
(s/keys :req-un [::state]))
|
||||
|
||||
(def state {:state ""})
|
||||
|
||||
(defn store-backup-repository-state [s]
|
||||
(spit "backup-repository-state.edn" s))
|
||||
|
||||
(defn read-backup-repository-state []
|
||||
(try
|
||||
(with-open [r (io/reader "backup-repository-state.edn")]
|
||||
(edn/read (java.io.PushbackReader. r)))
|
||||
|
||||
(catch java.io.IOException e
|
||||
(printf "Couldn't open '%s': %s\n" "backup-repository-state.edn" (.getMessage e)))
|
||||
(catch RuntimeException e
|
||||
(printf "Error parsing edn file '%s': %s\n" "backup-repository-state.edn" (.getMessage e)))))
|
||||
|
||||
(defn read-secret [s]
|
||||
(slurp (str "/var/run/secrets/" s)))
|
||||
;"/var/run/secrets/rotation-credential-secret/rotation-credential"))
|
||||
|
||||
;(println (read-backup-repository-state))
|
||||
|
||||
;(println (:state (read-backup-repository-state)))
|
||||
|
||||
;(println (s/valid? ::backup-repository-state (read-backup-repository-state)))
|
||||
|
||||
(println (read-secret "rotation-credential-secret/rotation-credential"))
|
||||
(println (read-secret "backup-secrets/restic-password"))
|
||||
|
||||
(s/def ::new-password string?)
|
||||
(s/def ::old-password string?)
|
||||
(s/def ::password-state
|
||||
(s/keys :req-un [::new-password ::old-password]))
|
||||
|
||||
(defn rotate []
|
||||
(let [state {:new-password (read-secret "rotation-credential-secret/rotation-credential")
|
||||
:old-password (read-secret "backup-secrets/restic-password")}]
|
||||
(store-backup-repository-state (prn-str state))))
|
||||
(rotate)
|
|
@ -1,7 +0,0 @@
|
|||
FROM dda-backup:latest
|
||||
|
||||
# install it
|
||||
RUN apt update && apt install -qqy openjdk-17-jre-headless
|
||||
ADD resources /tmp/
|
||||
RUN rm -rf /root/.m2
|
||||
RUN /tmp/install-test.bb
|
|
@ -1,4 +0,0 @@
|
|||
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
||||
org.domaindrivenarchitecture/dda-backup {:mvn/version "0.1.1-SNAPSHOT"}}}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/env bb
|
||||
|
||||
(require '[babashka.tasks :as tasks])
|
||||
|
||||
(defn curl-and-check!
|
||||
[filename artifact-url sha256-url]
|
||||
(let [filepath (str "/tmp/" filename)]
|
||||
(tasks/shell "curl" "-SsLo" filepath artifact-url)
|
||||
(tasks/shell "curl" "-SsLo" "/tmp/checksum" sha256-url)
|
||||
(tasks/shell "bash" "-c" (str "echo \" " filepath "\"|tee -a /tmp/checksum"))
|
||||
;(tasks/shell "sha256sum" "-c" "--status" "/tmp/checksum")
|
||||
))
|
||||
|
||||
(defn tar-install!
|
||||
[filename binname]
|
||||
(let [filepath (str "/tmp/" filename)]
|
||||
(tasks/shell "tar" "-C" "/tmp" "-xzf" filepath)
|
||||
(tasks/shell "install" "-m" "0700" "-o" "root" "-g" "root" (str "/tmp/" binname) "/usr/local/bin/")))
|
||||
|
||||
(defn install!
|
||||
[filename]
|
||||
(tasks/shell "install" "-m" "0700" "-o" "root" "-g" "root" (str "/tmp/" filename) "/usr/local/bin/"))
|
||||
|
||||
(tasks/shell "bb" "/tmp/test.bb")
|
||||
(curl-and-check!
|
||||
"provs-syspec.jar"
|
||||
"https://repo.prod.meissa.de/attachments/0a1da41e-aa5b-4a3e-a3b1-215cf2d5b021"
|
||||
"https://repo.prod.meissa.de/attachments/f227cf65-cb0f-46a7-a6cd-28f46917412a")
|
||||
(install! "provs-syspec.jar")
|
||||
(tasks/shell "apt" "update")
|
||||
(tasks/shell "apt" "install" "-qqy" "openjdk-17-jre-headless")
|
||||
(tasks/shell "java" "-jar" "/usr/local/bin/provs-syspec.jar" "local" "-c" "/tmp/spec.yml" )
|
|
@ -1,7 +0,0 @@
|
|||
package:
|
||||
- name: "restic"
|
||||
|
||||
command:
|
||||
- command: "bb -h"
|
||||
- command: "/tmp/test.bb"
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#!/usr/bin/env bb
|
||||
|
||||
(require '[babashka.tasks :as tasks]
|
||||
'[dda.backup.management :as mgm])
|
||||
|
||||
(defn restic-repo-init!
|
||||
[]
|
||||
(spit "restic-pwd" "ThePassword")
|
||||
(mgm/init! {:password-file "restic-pwd"
|
||||
:restic-repository "restic-repo"}))
|
||||
|
||||
(defn restic-backup!
|
||||
[]
|
||||
(tasks/shell "mkdir" "test-backup")
|
||||
(spit "test-backup/file" "I was here")
|
||||
(tasks/shell "restic" "backup" "--password-file" "restic-pwd" "--repo" "restic-repo" "test-backup"))
|
||||
|
||||
(defn restic-restore!
|
||||
[]
|
||||
(tasks/shell "mkdir" "test-restore")
|
||||
(tasks/shell "restic" "restore" "--password-file" "restic-pwd" "--repo" "restic-repo" "--target" "test-restore" "latest")
|
||||
)
|
||||
|
||||
|
||||
(restic-repo-init!)
|
||||
(restic-backup!)
|
||||
(restic-restore!)
|
|
@ -1,56 +0,0 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "clj-cljs"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_AND_MODULE",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
||||
|
||||
build = DevopsImageBuild(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def image(project):
|
||||
build = get_devops_build(project)
|
||||
build.image()
|
||||
|
||||
|
||||
@task
|
||||
def drun(project):
|
||||
build = get_devops_build(project)
|
||||
build.drun()
|
||||
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
build = get_devops_build(project)
|
||||
build.test()
|
||||
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.dockerhub_login()
|
||||
build.dockerhub_publish()
|
|
@ -1,4 +0,0 @@
|
|||
FROM node:lts-bookworm-slim
|
||||
|
||||
ADD resources /tmp
|
||||
RUN /tmp/install.sh
|
|
@ -1,45 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
mkdir -p /usr/share/man/man1
|
||||
apt-get -qqy install curl openjdk-17-jre-headless leiningen
|
||||
|
||||
# shadow-cljs
|
||||
npm install -g npm
|
||||
npm install -g --save-dev shadow-cljs
|
||||
|
||||
# download kubeconform & graalvm
|
||||
kubeconform_version="0.6.4"
|
||||
|
||||
curl -SsLo /tmp/kubeconform-linux-amd64.tar.gz https://github.com/yannh/kubeconform/releases/download/v${kubeconform_version}/kubeconform-linux-amd64.tar.gz
|
||||
curl -SsLo /tmp/CHECKSUMS https://github.com/yannh/kubeconform/releases/download/v${kubeconform_version}/CHECKSUMS
|
||||
|
||||
# checksum kubeconform
|
||||
checksum
|
||||
|
||||
# install kubeconform
|
||||
tar -C /usr/local/bin -xf /tmp/kubeconform-linux-amd64.tar.gz --exclude=LICENSE
|
||||
|
||||
#install pyb
|
||||
apt-get -qqy install python3 python3-pip git
|
||||
pip3 install pybuilder 'ddadevops>=4.7.0' deprecation dda-python-terraform boto3 pyyaml inflection --break-system-packages
|
||||
|
||||
#check
|
||||
lein --help
|
||||
|
||||
cleanupDocker
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
function checksum() {
|
||||
awk '{print $1 " /tmp/" $2}' /tmp/CHECKSUMS|sed -n '2p' > /tmp/kubeconform-checksum
|
||||
cat /tmp/kubeconform-checksum
|
||||
sha256sum -c --status /tmp/kubeconform-checksum
|
||||
}
|
||||
|
||||
source /tmp/install_functions_debian.sh
|
||||
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
|
@ -1,6 +0,0 @@
|
|||
FROM debian:stable-slim
|
||||
|
||||
ADD resources /tmp
|
||||
RUN /tmp/install.sh
|
||||
ENV LANG=en_US.UTF-8 \
|
||||
JAVA_HOME=/usr/lib/jvm/graalvm
|
|
@ -1,57 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
apt-get -qqy install curl git openjdk-17-jre-headless leiningen build-essential libz-dev zlib1g-dev
|
||||
|
||||
|
||||
# download kubeconform & graalvm
|
||||
kubeconform_version="0.6.4"
|
||||
graalvm_jdk_version="21.0.2"
|
||||
|
||||
curl -SsLo /tmp/kubeconform-linux-amd64.tar.gz https://github.com/yannh/kubeconform/releases/download/v${kubeconform_version}/kubeconform-linux-amd64.tar.gz
|
||||
curl -SsLo /tmp/CHECKSUMS https://github.com/yannh/kubeconform/releases/download/v${kubeconform_version}/CHECKSUMS
|
||||
curl -SsLo /tmp/graalvm-community-jdk.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${graalvm_jdk_version}/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz
|
||||
curl -SsLo /tmp/graalvm-checksum https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-${graalvm_jdk_version}/graalvm-community-jdk-${graalvm_jdk_version}_linux-x64_bin.tar.gz.sha256
|
||||
|
||||
# checksum kubeconform & graalvm-jdk
|
||||
checksum
|
||||
|
||||
# install kubeconform
|
||||
tar -C /usr/local/bin -xf /tmp/kubeconform-linux-amd64.tar.gz --exclude=LICENSE
|
||||
|
||||
# install graalvm
|
||||
tar -C /usr/lib/jvm/ -xf /tmp/graalvm-community-jdk.tar.gz
|
||||
dirname_graalvm=$(ls /usr/lib/jvm/|grep -e graa)
|
||||
ln -s /usr/lib/jvm/$dirname_graalvm /usr/lib/jvm/graalvm
|
||||
ln -s /usr/lib/jvm/graalvm/bin/gu /usr/local/bin
|
||||
update-alternatives --install /usr/bin/java java /usr/lib/jvm/graalvm/bin/java 2
|
||||
ln -s /usr/lib/jvm/graalvm/bin/native-image /usr/local/bin
|
||||
|
||||
#install pyb
|
||||
apt-get -qqy install python3 python3-pip
|
||||
pip3 install pybuilder 'ddadevops>=4.7.0' deprecation dda-python-terraform boto3 pyyaml inflection --break-system-packages
|
||||
|
||||
#check
|
||||
native-image --version
|
||||
lein -v
|
||||
|
||||
cleanupDocker
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
function checksum() {
|
||||
#kubeconform
|
||||
awk '{print $1 " /tmp/" $2}' /tmp/CHECKSUMS|sed -n '2p' > /tmp/kubeconform-checksum
|
||||
sha256sum -c --status /tmp/kubeconform-checksum
|
||||
|
||||
#graalvm
|
||||
echo " /tmp/graalvm-community-jdk.tar.gz"|tee -a /tmp/graalvm-checksum
|
||||
sha256sum -c --status /tmp/graalvm-checksum
|
||||
}
|
||||
|
||||
source /tmp/install_functions_debian.sh
|
||||
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
|
@ -1,18 +1,14 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "clj"
|
||||
name = "clojure"
|
||||
MODULE = "image"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
|
@ -21,8 +17,6 @@ def initialize(project):
|
|||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_AND_MODULE",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.10-alpine
|
||||
FROM node:lts-buster-slim
|
||||
|
||||
ADD resources /tmp
|
||||
RUN /tmp/install.sh
|
2
infrastructure/clojure/image/resources/CHECKSUMS
Normal file
2
infrastructure/clojure/image/resources/CHECKSUMS
Normal file
|
@ -0,0 +1,2 @@
|
|||
d7a5cb848b783c15119316d716d8a74bf11c9e3ab050f3adf28e0678a6018467 kubeconform-v0.4.7.tar.gz
|
||||
bbd3e03025168172a76c2a29e6a14c1c37e3476b30774259c3ef5952fb86f470 graalvm-ce-java11-linux-amd64-21.2.0.tar.gz
|
43
infrastructure/clojure/image/resources/install.sh
Executable file
43
infrastructure/clojure/image/resources/install.sh
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
function main() {
|
||||
upgradeSystem
|
||||
|
||||
mkdir -p /usr/share/man/man1
|
||||
apt -qqy install openjdk-11-jre-headless leiningen curl build-essential libz-dev zlib1g-dev
|
||||
|
||||
# shadow-cljs
|
||||
npm install -g --save-dev shadow-cljs
|
||||
|
||||
# download kubeconform & graalvm
|
||||
curl -Lo /tmp/kubeconform-v0.4.7.tar.gz https://github.com/yannh/kubeconform/releases/download/v0.4.7/kubeconform-linux-amd64.tar.gz
|
||||
curl -Lo /tmp/graalvm-ce-java11-linux-amd64-21.2.0.tar.gz https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.2.0/graalvm-ce-java11-linux-amd64-21.2.0.tar.gz
|
||||
|
||||
# checksum
|
||||
cd /tmp
|
||||
sha256sum --check CHECKSUMS
|
||||
|
||||
# install kubeconform
|
||||
tar -xf /tmp/kubeconform-v0.4.7.tar.gz
|
||||
cp kubeconform /usr/local/bin
|
||||
|
||||
# install graalvm
|
||||
tar -xzf graalvm-ce-java11-linux-amd64-21.2.0.tar.gz
|
||||
mv graalvm-ce-java11-21.2.0 /usr/lib/jvm/
|
||||
ln -s /usr/lib/jvm/graalvm-ce-java11-21.2.0 /usr/lib/jvm/graalvm
|
||||
ln -s /usr/lib/jvm/graalvm/bin/gu /usr/local/bin
|
||||
|
||||
update-alternatives --install /usr/bin/java java /usr/lib/jvm/graalvm/bin/java 2
|
||||
|
||||
gu install native-image
|
||||
ln -s /usr/lib/jvm/graalvm/bin/native-image /usr/local/bin
|
||||
|
||||
#install lein
|
||||
/tmp/lein.sh
|
||||
|
||||
cleanupDocker
|
||||
}
|
||||
|
||||
source /tmp/install_functions.sh
|
||||
main
|
423
infrastructure/clojure/image/resources/lein.sh
Executable file
423
infrastructure/clojure/image/resources/lein.sh
Executable file
|
@ -0,0 +1,423 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure this file is executable via `chmod a+x lein`, then place it
|
||||
# somewhere on your $PATH, like ~/bin. The rest of Leiningen will be
|
||||
# installed upon first run into the ~/.lein/self-installs directory.
|
||||
|
||||
function msg {
|
||||
echo "$@" 1>&2
|
||||
}
|
||||
|
||||
export LEIN_VERSION="2.9.6"
|
||||
# Must be sha256sum, will be replaced by bin/release
|
||||
export LEIN_CHECKSUM='41c543f73eec4327dc20e60d5d820fc2a9dc772bc671610b9c385d9c4f5970b8'
|
||||
|
||||
case $LEIN_VERSION in
|
||||
*SNAPSHOT) SNAPSHOT="YES" ;;
|
||||
*) SNAPSHOT="NO" ;;
|
||||
esac
|
||||
|
||||
if [[ "$CLASSPATH" != "" ]]; then
|
||||
cat <<-'EOS' 1>&2
|
||||
WARNING: You have $CLASSPATH set, probably by accident.
|
||||
It is strongly recommended to unset this before proceeding.
|
||||
EOS
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]]; then
|
||||
delimiter=";"
|
||||
else
|
||||
delimiter=":"
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" == "cygwin" ]]; then
|
||||
cygwin=true
|
||||
else
|
||||
cygwin=false
|
||||
fi
|
||||
|
||||
function command_not_found {
|
||||
msg "Leiningen couldn't find $1 in your \$PATH ($PATH), which is required."
|
||||
exit 1
|
||||
}
|
||||
|
||||
function make_native_path {
|
||||
# ensure we have native paths
|
||||
if $cygwin && [[ "$1" == /* ]]; then
|
||||
echo -n "$(cygpath -wp "$1")"
|
||||
elif [[ "$OSTYPE" == "msys" && "$1" == /?/* ]]; then
|
||||
echo -n "$(sh -c "(cd $1 2</dev/null && pwd -W) || echo $1 | sed 's/^\\/\([a-z]\)/\\1:/g'")"
|
||||
else
|
||||
echo -n "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
# usage : add_path PATH_VAR [PATH]...
|
||||
function add_path {
|
||||
local path_var="$1"
|
||||
shift
|
||||
while [ -n "$1" ];do
|
||||
# http://bashify.com/?Useful_Techniques:Indirect_Variables:Indirect_Assignment
|
||||
if [[ -z ${!path_var} ]]; then
|
||||
export ${path_var}="$(make_native_path "$1")"
|
||||
else
|
||||
export ${path_var}="${!path_var}${delimiter}$(make_native_path "$1")"
|
||||
fi
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
function download_failed_message {
|
||||
cat <<-EOS 1>&2
|
||||
Failed to download $1 (exit code $2)
|
||||
It's possible your HTTP client's certificate store does not have the
|
||||
correct certificate authority needed. This is often caused by an
|
||||
out-of-date version of libssl. It's also possible that you're behind a
|
||||
firewall and haven't set HTTP_PROXY and HTTPS_PROXY.
|
||||
EOS
|
||||
}
|
||||
|
||||
function checksum_failed_message {
|
||||
cat <<-EOS 1>&2
|
||||
Failed to properly download $1
|
||||
The checksum was mismatched. and we could not verify the downloaded
|
||||
file. We expected a sha256 of
|
||||
$2 and actually had
|
||||
$3.
|
||||
We used '$SHASUM_CMD' to verify the downloaded file.
|
||||
EOS
|
||||
}
|
||||
|
||||
function self_install {
|
||||
if [ -r "$LEIN_JAR" ]; then
|
||||
cat <<-EOS 1>&2
|
||||
The self-install jar already exists at $LEIN_JAR.
|
||||
If you wish to re-download, delete it and rerun "$0 self-install".
|
||||
EOS
|
||||
exit 1
|
||||
fi
|
||||
msg "Downloading Leiningen to $LEIN_JAR now..."
|
||||
mkdir -p "$(dirname "$LEIN_JAR")"
|
||||
LEIN_URL="https://github.com/technomancy/leiningen/releases/download/$LEIN_VERSION/leiningen-$LEIN_VERSION-standalone.zip"
|
||||
$HTTP_CLIENT "$LEIN_JAR.pending" "$LEIN_URL"
|
||||
local exit_code=$?
|
||||
if [ $exit_code == 0 ]; then
|
||||
printf "$LEIN_CHECKSUM $LEIN_JAR.pending\n" > "$LEIN_JAR.pending.shasum"
|
||||
$SHASUM_CMD -c "$LEIN_JAR.pending.shasum"
|
||||
if [ $? == 0 ]; then
|
||||
mv -f "$LEIN_JAR.pending" "$LEIN_JAR"
|
||||
else
|
||||
got_sum="$($SHASUM_CMD "$LEIN_JAR.pending" | cut -f 1 -d ' ')"
|
||||
checksum_failed_message "$LEIN_URL" "$LEIN_CHECKSUM" "$got_sum"
|
||||
rm "$LEIN_JAR.pending" 2> /dev/null
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
rm "$LEIN_JAR.pending" 2> /dev/null
|
||||
download_failed_message "$LEIN_URL" "$exit_code"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
NOT_FOUND=1
|
||||
ORIGINAL_PWD="$PWD"
|
||||
while [ ! -r "$PWD/project.clj" ] && [ "$PWD" != "/" ] && [ $NOT_FOUND -ne 0 ]
|
||||
do
|
||||
cd ..
|
||||
if [ "$(dirname "$PWD")" = "/" ]; then
|
||||
NOT_FOUND=0
|
||||
cd "$ORIGINAL_PWD"
|
||||
fi
|
||||
done
|
||||
|
||||
export LEIN_HOME="${LEIN_HOME:-"$HOME/.lein"}"
|
||||
|
||||
for f in "/etc/leinrc" "$LEIN_HOME/leinrc" ".leinrc"; do
|
||||
if [ -e "$f" ]; then
|
||||
source "$f"
|
||||
fi
|
||||
done
|
||||
|
||||
if $cygwin; then
|
||||
export LEIN_HOME=$(cygpath -w "$LEIN_HOME")
|
||||
fi
|
||||
|
||||
LEIN_JAR="$LEIN_HOME/self-installs/leiningen-$LEIN_VERSION-standalone.jar"
|
||||
|
||||
# normalize $0 on certain BSDs
|
||||
if [ "$(dirname "$0")" = "." ]; then
|
||||
SCRIPT="$(which "$(basename "$0")")"
|
||||
if [ -z "$SCRIPT" ]; then
|
||||
SCRIPT="$0"
|
||||
fi
|
||||
else
|
||||
SCRIPT="$0"
|
||||
fi
|
||||
|
||||
# resolve symlinks to the script itself portably
|
||||
while [ -h "$SCRIPT" ] ; do
|
||||
ls=$(ls -ld "$SCRIPT")
|
||||
link=$(expr "$ls" : '.*-> \(.*\)$')
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
SCRIPT="$link"
|
||||
else
|
||||
SCRIPT="$(dirname "$SCRIPT"$)/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
BIN_DIR="$(dirname "$SCRIPT")"
|
||||
|
||||
export LEIN_JVM_OPTS="${LEIN_JVM_OPTS-"-Xverify:none -XX:+TieredCompilation -XX:TieredStopAtLevel=1"}"
|
||||
|
||||
# This needs to be defined before we call HTTP_CLIENT below
|
||||
if [ "$HTTP_CLIENT" = "" ]; then
|
||||
if type -p curl >/dev/null 2>&1; then
|
||||
if [ "$https_proxy" != "" ]; then
|
||||
CURL_PROXY="-x $https_proxy"
|
||||
fi
|
||||
HTTP_CLIENT="curl $CURL_PROXY -f -L -o"
|
||||
else
|
||||
HTTP_CLIENT="wget -O"
|
||||
fi
|
||||
fi
|
||||
|
||||
# This needs to be defined before we call SHASUM_CMD below
|
||||
if [ "$SHASUM_CMD" = "" ]; then
|
||||
if type -p sha256sum >/dev/null 2>&1; then
|
||||
export SHASUM_CMD="sha256sum"
|
||||
elif type -p shasum >/dev/null 2>&1; then
|
||||
export SHASUM_CMD="shasum --algorithm 256"
|
||||
elif type -p sha256 >/dev/null 2>&1; then
|
||||
export SHASUM_CMD="sha256 -q"
|
||||
else
|
||||
command_not_found sha256sum
|
||||
fi
|
||||
fi
|
||||
|
||||
# When :eval-in :classloader we need more memory
|
||||
grep -E -q '^\s*:eval-in\s+:classloader\s*$' project.clj 2> /dev/null && \
|
||||
export LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Xms64m -Xmx512m"
|
||||
|
||||
if [ -r "$BIN_DIR/../src/leiningen/version.clj" ]; then
|
||||
# Running from source checkout
|
||||
LEIN_DIR="$(cd $(dirname "$BIN_DIR");pwd -P)"
|
||||
|
||||
# Need to use lein release to bootstrap the leiningen-core library (for aether)
|
||||
if [ ! -r "$LEIN_DIR/leiningen-core/.lein-bootstrap" ]; then
|
||||
cat <<-'EOS' 1>&2
|
||||
Leiningen is missing its dependencies.
|
||||
Please run "lein bootstrap" in the leiningen-core/ directory
|
||||
with a stable release of Leiningen. See CONTRIBUTING.md for details.
|
||||
EOS
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# If project.clj for lein or leiningen-core changes, we must recalculate
|
||||
LAST_PROJECT_CHECKSUM=$(cat "$LEIN_DIR/.lein-project-checksum" 2> /dev/null)
|
||||
PROJECT_CHECKSUM=$(sum "$LEIN_DIR/project.clj" "$LEIN_DIR/leiningen-core/project.clj")
|
||||
if [ "$PROJECT_CHECKSUM" != "$LAST_PROJECT_CHECKSUM" ]; then
|
||||
if [ -r "$LEIN_DIR/.lein-classpath" ]; then
|
||||
rm "$LEIN_DIR/.lein-classpath"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Use bin/lein to calculate its own classpath.
|
||||
if [ ! -r "$LEIN_DIR/.lein-classpath" ] && [ "$1" != "classpath" ]; then
|
||||
msg "Recalculating Leiningen's classpath."
|
||||
cd "$LEIN_DIR"
|
||||
|
||||
LEIN_NO_USER_PROFILES=1 "$LEIN_DIR/bin/lein" classpath .lein-classpath
|
||||
sum "$LEIN_DIR/project.clj" "$LEIN_DIR/leiningen-core/project.clj" > \
|
||||
.lein-project-checksum
|
||||
cd -
|
||||
fi
|
||||
|
||||
mkdir -p "$LEIN_DIR/target/classes"
|
||||
export LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Dclojure.compile.path=$LEIN_DIR/target/classes"
|
||||
add_path CLASSPATH "$LEIN_DIR/leiningen-core/src/" "$LEIN_DIR/leiningen-core/resources/" \
|
||||
"$LEIN_DIR/test:$LEIN_DIR/target/classes" "$LEIN_DIR/src" ":$LEIN_DIR/resources"
|
||||
|
||||
if [ -r "$LEIN_DIR/.lein-classpath" ]; then
|
||||
add_path CLASSPATH "$(cat "$LEIN_DIR/.lein-classpath" 2> /dev/null)"
|
||||
else
|
||||
add_path CLASSPATH "$(cat "$LEIN_DIR/leiningen-core/.lein-bootstrap" 2> /dev/null)"
|
||||
fi
|
||||
else # Not running from a checkout
|
||||
add_path CLASSPATH "$LEIN_JAR"
|
||||
|
||||
if [ "$LEIN_USE_BOOTCLASSPATH" != "no" ]; then
|
||||
LEIN_JVM_OPTS="-Xbootclasspath/a:$LEIN_JAR $LEIN_JVM_OPTS"
|
||||
fi
|
||||
|
||||
if [ ! -r "$LEIN_JAR" -a "$1" != "self-install" ]; then
|
||||
self_install
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVA_CMD" ] && ! type -f java >/dev/null
|
||||
then
|
||||
msg "Leiningen couldn't find 'java' executable, which is required."
|
||||
msg "Please either set JAVA_CMD or put java (>=1.6) in your \$PATH ($PATH)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export LEIN_JAVA_CMD="${LEIN_JAVA_CMD:-${JAVA_CMD:-java}}"
|
||||
|
||||
if [[ -z "${DRIP_INIT+x}" && "$(basename "$LEIN_JAVA_CMD")" == *drip* ]]; then
|
||||
export DRIP_INIT="$(printf -- '-e\n(require (quote leiningen.repl))')"
|
||||
export DRIP_INIT_CLASS="clojure.main"
|
||||
fi
|
||||
|
||||
# Support $JAVA_OPTS for backwards-compatibility.
|
||||
export JVM_OPTS="${JVM_OPTS:-"$JAVA_OPTS"}"
|
||||
|
||||
# Handle jline issue with cygwin not propagating OSTYPE through java subprocesses: https://github.com/jline/jline2/issues/62
|
||||
cygterm=false
|
||||
if $cygwin; then
|
||||
case "$TERM" in
|
||||
rxvt* | xterm* | vt*) cygterm=true ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if $cygterm; then
|
||||
LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Djline.terminal=jline.UnixTerminal"
|
||||
stty -icanon min 1 -echo > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# TODO: investigate http://skife.org/java/unix/2011/06/20/really_executable_jars.html
|
||||
# If you're packaging this for a package manager (.deb, homebrew, etc)
|
||||
# you need to remove the self-install and upgrade functionality or see lein-pkg.
|
||||
if [ "$1" = "self-install" ]; then
|
||||
if [ -r "$BIN_DIR/../src/leiningen/version.clj" ]; then
|
||||
cat <<-'EOS' 1>&2
|
||||
Running self-install from a checkout is not supported.
|
||||
See CONTRIBUTING.md for SNAPSHOT-specific build instructions.
|
||||
EOS
|
||||
exit 1
|
||||
fi
|
||||
msg "Manual self-install is deprecated; it will run automatically when necessary."
|
||||
self_install
|
||||
elif [ "$1" = "upgrade" ] || [ "$1" = "downgrade" ]; then
|
||||
if [ "$LEIN_DIR" != "" ]; then
|
||||
msg "The upgrade task is not meant to be run from a checkout."
|
||||
exit 1
|
||||
fi
|
||||
if [ $SNAPSHOT = "YES" ]; then
|
||||
cat <<-'EOS' 1>&2
|
||||
The upgrade task is only meant for stable releases.
|
||||
See the "Bootstrapping" section of CONTRIBUTING.md.
|
||||
EOS
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -w "$SCRIPT" ]; then
|
||||
msg "You do not have permission to upgrade the installation in $SCRIPT"
|
||||
exit 1
|
||||
else
|
||||
TARGET_VERSION="${2:-stable}"
|
||||
echo "The script at $SCRIPT will be upgraded to the latest $TARGET_VERSION version."
|
||||
echo -n "Do you want to continue [Y/n]? "
|
||||
read RESP
|
||||
case "$RESP" in
|
||||
y|Y|"")
|
||||
echo
|
||||
msg "Upgrading..."
|
||||
TARGET="/tmp/lein-${$}-upgrade"
|
||||
if $cygwin; then
|
||||
TARGET=$(cygpath -w "$TARGET")
|
||||
fi
|
||||
LEIN_SCRIPT_URL="https://github.com/technomancy/leiningen/raw/$TARGET_VERSION/bin/lein"
|
||||
$HTTP_CLIENT "$TARGET" "$LEIN_SCRIPT_URL"
|
||||
if [ $? == 0 ]; then
|
||||
cmp -s "$TARGET" "$SCRIPT"
|
||||
if [ $? == 0 ]; then
|
||||
msg "Leiningen is already up-to-date."
|
||||
fi
|
||||
mv "$TARGET" "$SCRIPT" && chmod +x "$SCRIPT"
|
||||
unset CLASSPATH
|
||||
exec "$SCRIPT" version
|
||||
else
|
||||
download_failed_message "$LEIN_SCRIPT_URL"
|
||||
fi;;
|
||||
*)
|
||||
msg "Aborted."
|
||||
exit 1;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
if $cygwin; then
|
||||
# When running on Cygwin, use Windows-style paths for java
|
||||
ORIGINAL_PWD=$(cygpath -w "$ORIGINAL_PWD")
|
||||
fi
|
||||
|
||||
# apply context specific CLASSPATH entries
|
||||
if [ -f .lein-classpath ]; then
|
||||
add_path CLASSPATH "$(cat .lein-classpath)"
|
||||
fi
|
||||
|
||||
if [ -n "$DEBUG" ]; then
|
||||
msg "Leiningen's classpath: $CLASSPATH"
|
||||
fi
|
||||
|
||||
if [ -r .lein-fast-trampoline ]; then
|
||||
export LEIN_FAST_TRAMPOLINE='y'
|
||||
fi
|
||||
|
||||
if [ "$LEIN_FAST_TRAMPOLINE" != "" ] && [ -r project.clj ]; then
|
||||
INPUTS="$* $(cat project.clj) $LEIN_VERSION $(test -f "$LEIN_HOME/profiles.clj" && cat "$LEIN_HOME/profiles.clj") $(test -f profiles.clj && cat profiles.clj)"
|
||||
|
||||
INPUT_CHECKSUM=$(echo "$INPUTS" | $SHASUM_CMD | cut -f 1 -d " ")
|
||||
# Just don't change :target-path in project.clj, mkay?
|
||||
TRAMPOLINE_FILE="target/trampolines/$INPUT_CHECKSUM"
|
||||
else
|
||||
if hash mktemp 2>/dev/null; then
|
||||
# Check if mktemp is available before using it
|
||||
TRAMPOLINE_FILE="$(mktemp /tmp/lein-trampoline-XXXXXXXXXXXXX)"
|
||||
else
|
||||
TRAMPOLINE_FILE="/tmp/lein-trampoline-$$"
|
||||
fi
|
||||
trap 'rm -f $TRAMPOLINE_FILE' EXIT
|
||||
fi
|
||||
|
||||
if $cygwin; then
|
||||
TRAMPOLINE_FILE=$(cygpath -w "$TRAMPOLINE_FILE")
|
||||
fi
|
||||
|
||||
if [ "$INPUT_CHECKSUM" != "" ] && [ -r "$TRAMPOLINE_FILE" ]; then
|
||||
if [ -n "$DEBUG" ]; then
|
||||
msg "Fast trampoline with $TRAMPOLINE_FILE."
|
||||
fi
|
||||
exec sh -c "exec $(cat "$TRAMPOLINE_FILE")"
|
||||
else
|
||||
export TRAMPOLINE_FILE
|
||||
"$LEIN_JAVA_CMD" \
|
||||
-Dfile.encoding=UTF-8 \
|
||||
-Dmaven.wagon.http.ssl.easy=false \
|
||||
-Dmaven.wagon.rto=10000 \
|
||||
$LEIN_JVM_OPTS \
|
||||
-Dleiningen.input-checksum="$INPUT_CHECKSUM" \
|
||||
-Dleiningen.original.pwd="$ORIGINAL_PWD" \
|
||||
-Dleiningen.script="$SCRIPT" \
|
||||
-classpath "$CLASSPATH" \
|
||||
clojure.main -m leiningen.core.main "$@"
|
||||
|
||||
EXIT_CODE=$?
|
||||
|
||||
if $cygterm ; then
|
||||
stty icanon echo > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
if [ -r "$TRAMPOLINE_FILE" ] && [ "$LEIN_TRAMPOLINE_WARMUP" = "" ]; then
|
||||
TRAMPOLINE="$(cat "$TRAMPOLINE_FILE")"
|
||||
if [ "$INPUT_CHECKSUM" = "" ]; then # not using fast trampoline
|
||||
rm "$TRAMPOLINE_FILE"
|
||||
fi
|
||||
if [ "$TRAMPOLINE" = "" ]; then
|
||||
exit $EXIT_CODE
|
||||
else
|
||||
exec sh -c "exec $TRAMPOLINE"
|
||||
fi
|
||||
else
|
||||
exit $EXIT_CODE
|
||||
fi
|
||||
fi
|
||||
fi
|
11
infrastructure/clojure/test/Dockerfile
Normal file
11
infrastructure/clojure/test/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
|||
FROM clojure
|
||||
|
||||
RUN apt update
|
||||
RUN apt -yqq --no-install-recommends --yes install curl default-jre-headless
|
||||
|
||||
RUN curl -L -o /tmp/serverspec.jar \
|
||||
https://github.com/DomainDrivenArchitecture/dda-serverspec-crate/releases/download/2.0.0/dda-serverspec-standalone.jar
|
||||
|
||||
COPY serverspec.edn /tmp/serverspec.edn
|
||||
|
||||
RUN java -jar /tmp/serverspec.jar /tmp/serverspec.edn -v
|
1
infrastructure/clojure/test/serverspec.edn
Normal file
1
infrastructure/clojure/test/serverspec.edn
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,57 +0,0 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "ddadevops"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_ONLY",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.9.0")
|
||||
|
||||
build = DevopsImageBuild(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def image(project):
|
||||
build = get_devops_build(project)
|
||||
build.image()
|
||||
|
||||
|
||||
@task
|
||||
def drun(project):
|
||||
build = get_devops_build(project)
|
||||
build.drun()
|
||||
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
build = get_devops_build(project)
|
||||
build.test()
|
||||
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.dockerhub_login()
|
||||
build.dockerhub_publish()
|
|
@ -1,5 +0,0 @@
|
|||
FROM python:3.10-alpine
|
||||
|
||||
ADD resources /tmp
|
||||
|
||||
RUN /tmp/install.sh
|
|
@ -1,19 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
apk add --no-cache python3 py3-pip openssl-dev bash git curl
|
||||
python3 -m pip install -U pip
|
||||
pip3 install pybuilder ddadevops deprecation dda-python-terraform boto3 pyyaml inflection
|
||||
|
||||
cleanupDocker
|
||||
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
source /tmp/install_functions_alpine.sh
|
||||
main
|
|
@ -1,19 +1,14 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "python"
|
||||
name = "devops-build"
|
||||
MODULE = "image"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
|
@ -22,8 +17,6 @@ def initialize(project):
|
|||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_AND_MODULE",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
6
infrastructure/devops-build/image/Dockerfile
Normal file
6
infrastructure/devops-build/image/Dockerfile
Normal file
|
@ -0,0 +1,6 @@
|
|||
FROM docker:latest
|
||||
|
||||
RUN set -eux;
|
||||
RUN apk add --no-cache build-base rust python3 python3-dev py3-pip py3-setuptools py3-wheel libffi-dev openssl-dev cargo bash git;
|
||||
RUN python3 -m pip install -U pip;
|
||||
RUN pip3 install pybuilder ddadevops deprecation dda-python-terraform boto3 pyyaml;
|
11
infrastructure/devops-build/test/Dockerfile
Normal file
11
infrastructure/devops-build/test/Dockerfile
Normal file
|
@ -0,0 +1,11 @@
|
|||
FROM devops-build
|
||||
|
||||
RUN apk update
|
||||
RUN apk add curl openjdk8
|
||||
|
||||
RUN curl -L -o /tmp/serverspec.jar \
|
||||
https://github.com/DomainDrivenArchitecture/dda-serverspec-crate/releases/download/2.0.0/dda-serverspec-standalone.jar
|
||||
|
||||
COPY serverspec.edn /tmp/serverspec.edn
|
||||
|
||||
RUN java -jar /tmp/serverspec.jar /tmp/serverspec.edn -v
|
1
infrastructure/devops-build/test/serverspec.edn
Normal file
1
infrastructure/devops-build/test/serverspec.edn
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,57 +0,0 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "dind"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_AND_MODULE",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.7.0")
|
||||
|
||||
build = DevopsImageBuild(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def image(project):
|
||||
build = get_devops_build(project)
|
||||
build.image()
|
||||
|
||||
|
||||
@task
|
||||
def drun(project):
|
||||
build = get_devops_build(project)
|
||||
build.drun()
|
||||
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
build = get_devops_build(project)
|
||||
build.test()
|
||||
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.dockerhub_login()
|
||||
build.dockerhub_publish()
|
|
@ -1,5 +0,0 @@
|
|||
FROM docker:latest
|
||||
|
||||
WORKDIR /tmp
|
||||
ADD resources ./
|
||||
RUN ./install.sh
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
apk add --no-cache python3 py3-pip openssl-dev bash git
|
||||
pip3 install --break-system-packages pybuilder ddadevops deprecation dda-python-terraform boto3 pyyaml inflection
|
||||
|
||||
cleanupDocker
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
source /tmp/install_functions_alpine.sh
|
||||
main
|
|
@ -1,57 +0,0 @@
|
|||
from os import environ
|
||||
from datetime import datetime
|
||||
from pybuilder.core import task, init
|
||||
from ddadevops import *
|
||||
|
||||
name = "ddadevops"
|
||||
MODULE = "kotlin"
|
||||
PROJECT_ROOT_PATH = "../.."
|
||||
version = "4.13.2-dev"
|
||||
|
||||
|
||||
@init
|
||||
def initialize(project):
|
||||
image_tag = version
|
||||
if "dev" in image_tag:
|
||||
image_tag += datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
|
||||
|
||||
input = {
|
||||
"name": name,
|
||||
"module": MODULE,
|
||||
"stage": "notused",
|
||||
"project_root_path": PROJECT_ROOT_PATH,
|
||||
"build_types": ["IMAGE"],
|
||||
"mixin_types": [],
|
||||
"image_naming": "NAME_AND_MODULE",
|
||||
"image_tag": f"{image_tag}",
|
||||
}
|
||||
|
||||
project.build_depends_on("ddadevops>=4.0.0")
|
||||
|
||||
build = DevopsImageBuild(project, input)
|
||||
build.initialize_build_dir()
|
||||
|
||||
|
||||
@task
|
||||
def image(project):
|
||||
build = get_devops_build(project)
|
||||
build.image()
|
||||
|
||||
|
||||
@task
|
||||
def drun(project):
|
||||
build = get_devops_build(project)
|
||||
build.drun()
|
||||
|
||||
|
||||
@task
|
||||
def test(project):
|
||||
build = get_devops_build(project)
|
||||
build.test()
|
||||
|
||||
|
||||
@task
|
||||
def publish(project):
|
||||
build = get_devops_build(project)
|
||||
build.dockerhub_login()
|
||||
build.dockerhub_publish()
|
|
@ -1,4 +0,0 @@
|
|||
FROM debian:stable-slim
|
||||
|
||||
ADD resources /tmp
|
||||
RUN /tmp/install.sh
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
apt-get -qqy install curl git kotlin gradle iputils-ping ssh python3 python3-pip
|
||||
|
||||
pip3 install --break-system-packages pybuilder 'ddadevops>=4.7.0' deprecation dda-python-terraform boto3 pyyaml inflection
|
||||
|
||||
cleanupDocker
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
source /tmp/install_functions_debian.sh
|
||||
DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes main
|
|
@ -1,20 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
set -exo pipefail
|
||||
|
||||
function main() {
|
||||
{
|
||||
upgradeSystem
|
||||
|
||||
apk add --no-cache build-base rust python3 python3-dev py3-pip py3-setuptools py3-wheel libffi-dev openssl-dev cargo bash git curl
|
||||
python3 -m pip install -U pip
|
||||
pip3 install pybuilder ddadevops deprecation dda-python-terraform boto3 pyyaml inflection \
|
||||
coverage flake8 flake8-polyfill mypy mypy-extensions pycodestyle pyflakes pylint pytest pytest-cov pytest-datafiles types-setuptools types-PyYAML
|
||||
|
||||
cleanupDocker
|
||||
|
||||
} > /dev/null
|
||||
}
|
||||
|
||||
source /tmp/install_functions_alpine.sh
|
||||
main
|
|
@ -4,9 +4,7 @@ from ..infrastructure import FileApi, ResourceApi, ImageApi
|
|||
|
||||
|
||||
class ImageBuildService:
|
||||
def __init__(
|
||||
self, file_api: FileApi, resource_api: ResourceApi, image_api: ImageApi
|
||||
):
|
||||
def __init__(self, file_api: FileApi, resource_api: ResourceApi, image_api: ImageApi):
|
||||
self.file_api = file_api
|
||||
self.resource_api = resource_api
|
||||
self.image_api = image_api
|
||||
|
@ -20,9 +18,7 @@ class ImageBuildService:
|
|||
)
|
||||
|
||||
def __copy_build_resource_file_from_package__(self, resource_name, devops: Devops):
|
||||
data = self.resource_api.read_resource(
|
||||
f"src/main/resources/docker/{resource_name}"
|
||||
)
|
||||
data = self.resource_api.read_resource(f"src/main/resources/docker/{resource_name}")
|
||||
self.file_api.write_data_to_file(
|
||||
Path(f"{devops.build_path()}/{resource_name}"), data
|
||||
)
|
||||
|
@ -31,16 +27,12 @@ class ImageBuildService:
|
|||
self.__copy_build_resource_file_from_package__(
|
||||
"image/resources/install_functions.sh", devops
|
||||
)
|
||||
self.__copy_build_resource_file_from_package__(
|
||||
"image/resources/install_functions_debian.sh", devops
|
||||
)
|
||||
self.__copy_build_resource_file_from_package__(
|
||||
"image/resources/install_functions_alpine.sh", devops
|
||||
)
|
||||
|
||||
def __copy_build_resources_from_dir__(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
self.file_api.cp_force(image.build_commons_path(), devops.build_path())
|
||||
self.file_api.cp_force(
|
||||
image.build_commons_path(), devops.build_path()
|
||||
)
|
||||
|
||||
def initialize_build_dir(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
|
@ -51,18 +43,13 @@ class ImageBuildService:
|
|||
else:
|
||||
self.__copy_build_resources_from_dir__(devops)
|
||||
self.file_api.cp_recursive("image", build_path)
|
||||
try:
|
||||
self.file_api.cp_recursive("test", build_path)
|
||||
except:
|
||||
print("Folder 'test' not found")
|
||||
|
||||
def image(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
self.image_api.image(image.image_name(), devops.build_path())
|
||||
self.image_api.image(devops.name, devops.build_path())
|
||||
|
||||
def drun(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
self.image_api.drun(image.image_name())
|
||||
self.image_api.drun(devops.name)
|
||||
|
||||
def dockerhub_login(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
|
@ -72,14 +59,9 @@ class ImageBuildService:
|
|||
|
||||
def dockerhub_publish(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
if image.image_tag is not None:
|
||||
self.image_api.dockerhub_publish(
|
||||
image.image_name(), image.image_dockerhub_user, image.image_tag
|
||||
)
|
||||
self.image_api.dockerhub_publish(
|
||||
image.image_name(), image.image_dockerhub_user, 'latest'
|
||||
devops.name, image.image_dockerhub_user, image.image_tag
|
||||
)
|
||||
|
||||
def test(self, devops: Devops):
|
||||
image = devops.specialized_builds[BuildType.IMAGE]
|
||||
self.image_api.test(image.image_name(), devops.build_path())
|
||||
self.image_api.test(devops.name, devops.build_path())
|
||||
|
|
|
@ -1,26 +1,18 @@
|
|||
import json
|
||||
from typing import List
|
||||
from pathlib import Path
|
||||
from ..infrastructure import GitApi, ArtifactDeploymentApi, BuildFileRepository
|
||||
from ..domain import Version, Release, ReleaseType, Artifact
|
||||
from ..infrastructure import GitApi, BuildFileRepository
|
||||
from ..domain import Version, Release, ReleaseType
|
||||
|
||||
|
||||
class ReleaseService:
|
||||
def __init__(
|
||||
self,
|
||||
git_api: GitApi,
|
||||
artifact_deployment_api: ArtifactDeploymentApi,
|
||||
build_file_repository: BuildFileRepository,
|
||||
):
|
||||
def __init__(self, git_api: GitApi, build_file_repository: BuildFileRepository):
|
||||
self.git_api = git_api
|
||||
self.artifact_deployment_api = artifact_deployment_api
|
||||
self.build_file_repository = build_file_repository
|
||||
|
||||
@classmethod
|
||||
def prod(cls, base_dir: str):
|
||||
return cls(
|
||||
GitApi(),
|
||||
ArtifactDeploymentApi(),
|
||||
BuildFileRepository(base_dir),
|
||||
)
|
||||
|
||||
|
@ -53,8 +45,7 @@ class ReleaseService:
|
|||
bump_version = release_version.create_bump()
|
||||
release_message = f"release: {release_version.to_string()}"
|
||||
bump_message = f"bump version to: {bump_version.to_string()}"
|
||||
release_tag = f"{release.release_tag_prefix}{release_version.to_string()}"
|
||||
self.git_api.tag_annotated(release_tag, release_message, 0)
|
||||
self.git_api.tag_annotated(release_version.to_string(), release_message, 0)
|
||||
self.__set_version_and_commit__(
|
||||
bump_version,
|
||||
release.build_files(),
|
||||
|
@ -62,41 +53,6 @@ class ReleaseService:
|
|||
)
|
||||
self.git_api.push_follow_tags()
|
||||
|
||||
def publish_artifacts(self, release: Release):
|
||||
token = str(release.release_artifact_token)
|
||||
release_id = self.__parse_forgejo_release_id__(
|
||||
self.artifact_deployment_api.create_forgejo_release(
|
||||
release.forgejo_release_api_endpoint(),
|
||||
release.version.to_string(),
|
||||
token,
|
||||
)
|
||||
)
|
||||
|
||||
artifacts_sums = []
|
||||
for artifact in release.release_artifacts:
|
||||
sha256 = self.artifact_deployment_api.calculate_sha256(artifact.path())
|
||||
sha512 = self.artifact_deployment_api.calculate_sha512(artifact.path())
|
||||
artifacts_sums += [Artifact(sha256), Artifact(sha512)]
|
||||
|
||||
artifacts = release.release_artifacts + artifacts_sums
|
||||
print(artifacts)
|
||||
for artifact in artifacts:
|
||||
print(str)
|
||||
self.artifact_deployment_api.add_asset_to_release(
|
||||
release.forgejo_release_asset_api_endpoint(release_id),
|
||||
artifact.path(),
|
||||
artifact.type(),
|
||||
token,
|
||||
)
|
||||
|
||||
def __parse_forgejo_release_id__(self, release_response: str) -> int:
|
||||
parsed = json.loads(release_response)
|
||||
try:
|
||||
result = parsed["id"]
|
||||
except:
|
||||
raise RuntimeError(str(parsed))
|
||||
return result
|
||||
|
||||
def __set_version_and_commit__(
|
||||
self, version: Version, build_file_ids: List[str], message: str
|
||||
):
|
||||
|
|
|
@ -17,7 +17,6 @@ from .provider_hetzner import Hetzner
|
|||
from .provider_aws import Aws
|
||||
from .provs_k3s import K3s
|
||||
from .release import Release
|
||||
from .artifact import Artifact
|
||||
from .credentials import Credentials, CredentialMapping, GopassType
|
||||
from .version import Version
|
||||
from .build_file import BuildFileType, BuildFile
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from .common import (
|
||||
Validateable,
|
||||
)
|
||||
|
||||
|
||||
class ArtifactType(Enum):
|
||||
TEXT = 0
|
||||
JAR = 1
|
||||
|
||||
|
||||
class Artifact(Validateable):
|
||||
def __init__(self, path: str):
|
||||
self.path_str = path
|
||||
|
||||
def path(self) -> Path:
|
||||
return Path(self.path_str)
|
||||
|
||||
def type(self) -> str:
|
||||
suffix = self.path().suffix
|
||||
match suffix:
|
||||
case ".jar":
|
||||
return "application/x-java-archive"
|
||||
case ".js":
|
||||
return "application/x-javascript"
|
||||
case _:
|
||||
return "text/plain"
|
||||
|
||||
def validate(self):
|
||||
result = []
|
||||
result += self.__validate_is_not_empty__("path_str")
|
||||
try:
|
||||
Path(self.path_str)
|
||||
except Exception as e:
|
||||
result += [f"path was not a valid: {e}"]
|
||||
return result
|
||||
|
||||
def __str__(self):
|
||||
return str(self.path())
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.__str__() == other.__str__()
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self.__str__().__hash__()
|
|
@ -11,7 +11,6 @@ class BuildFileType(Enum):
|
|||
JS = ".json"
|
||||
JAVA_GRADLE = ".gradle"
|
||||
JAVA_CLOJURE = ".clj"
|
||||
JAVA_CLOJURE_EDN = ".edn"
|
||||
PYTHON = ".py"
|
||||
|
||||
|
||||
|
@ -42,42 +41,42 @@ class BuildFile(Validateable):
|
|||
result = BuildFileType.JAVA_CLOJURE
|
||||
case ".py":
|
||||
result = BuildFileType.PYTHON
|
||||
case ".edn":
|
||||
result = BuildFileType.JAVA_CLOJURE_EDN
|
||||
case _:
|
||||
result = None
|
||||
return result
|
||||
|
||||
def __get_file_type_regex_str(self, file_type: BuildFileType):
|
||||
match file_type:
|
||||
case BuildFileType.JAVA_GRADLE:
|
||||
return r"(?P<pre_version>\bversion\s?=\s?)\"(?P<version>\d*\.\d*\.\d*(-SNAPSHOT)?)\""
|
||||
case BuildFileType.PYTHON:
|
||||
return r"(?P<pre_version>\bversion\s?=\s?)\"(?P<version>\d*\.\d*\.\d*(-SNAPSHOT|-dev\d*)?)\""
|
||||
case BuildFileType.JAVA_CLOJURE:
|
||||
return r"(?P<pre_version>\(defproject\s(\S)*\s)\"(?P<version>\d*\.\d*\.\d*(-SNAPSHOT)?)\""
|
||||
case BuildFileType.JAVA_CLOJURE_EDN:
|
||||
return r"(?P<pre_version>\:version\s+)\"(?P<version>\d*\.\d*\.\d*(-SNAPSHOT)?)\""
|
||||
case _:
|
||||
return ""
|
||||
|
||||
def get_version(self) -> Version:
|
||||
try:
|
||||
build_file_type = self.build_file_type()
|
||||
match build_file_type:
|
||||
match self.build_file_type():
|
||||
case BuildFileType.JS:
|
||||
version_str = json.loads(self.content)["version"]
|
||||
case (
|
||||
BuildFileType.JAVA_GRADLE
|
||||
| BuildFileType.PYTHON
|
||||
| BuildFileType.JAVA_CLOJURE
|
||||
| BuildFileType.JAVA_CLOJURE_EDN
|
||||
):
|
||||
version_str = re.search(
|
||||
self.__get_file_type_regex_str(build_file_type), self.content
|
||||
).group("version")
|
||||
case BuildFileType.JAVA_GRADLE:
|
||||
# TODO: '\nversion = ' will not parse all ?!
|
||||
version_line = re.search("\nversion = .*", self.content)
|
||||
version_line_group = version_line.group()
|
||||
version_string = re.search(
|
||||
"[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?", version_line_group
|
||||
)
|
||||
version_str = version_string.group()
|
||||
case BuildFileType.PYTHON:
|
||||
# TODO: '\nversion = ' will not parse all ?!
|
||||
version_line = re.search("\nversion = .*\n", self.content)
|
||||
version_line_group = version_line.group()
|
||||
version_string = re.search(
|
||||
"[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?(-dev)?[0-9]*",
|
||||
version_line_group,
|
||||
)
|
||||
version_str = version_string.group()
|
||||
case BuildFileType.JAVA_CLOJURE:
|
||||
# TODO: unsure about the trailing '\n' !
|
||||
version_line = re.search("\\(defproject .*\n", self.content)
|
||||
version_line_group = version_line.group()
|
||||
version_string = re.search(
|
||||
"[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?", version_line_group
|
||||
)
|
||||
version_str = version_string.group()
|
||||
except:
|
||||
raise RuntimeError(f"Version not found in file {self.file_path}")
|
||||
raise Exception(f"Version not found in file {self.file_path}")
|
||||
|
||||
result = Version.from_str(version_str, self.get_default_suffix())
|
||||
result.throw_if_invalid()
|
||||
|
@ -85,32 +84,38 @@ class BuildFile(Validateable):
|
|||
return result
|
||||
|
||||
def set_version(self, new_version: Version):
|
||||
|
||||
if new_version.is_snapshot():
|
||||
new_version.snapshot_suffix = self.get_default_suffix()
|
||||
|
||||
# TODO: How can we create regex-pattern constants to use them at both places?
|
||||
try:
|
||||
build_file_type = self.build_file_type()
|
||||
match build_file_type:
|
||||
match self.build_file_type():
|
||||
case BuildFileType.JS:
|
||||
json_data = json.loads(self.content)
|
||||
json_data["version"] = new_version.to_string()
|
||||
self.content = json.dumps(json_data, indent=4)
|
||||
case (
|
||||
BuildFileType.JAVA_GRADLE
|
||||
| BuildFileType.PYTHON
|
||||
| BuildFileType.JAVA_CLOJURE
|
||||
| BuildFileType.JAVA_CLOJURE_EDN
|
||||
):
|
||||
case BuildFileType.JAVA_GRADLE:
|
||||
substitute = re.sub(
|
||||
self.__get_file_type_regex_str(build_file_type),
|
||||
rf'\g<pre_version>"{new_version.to_string()}"',
|
||||
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"',
|
||||
f'\nversion = "{new_version.to_string()}"',
|
||||
self.content,
|
||||
)
|
||||
self.content = substitute
|
||||
case BuildFileType.PYTHON:
|
||||
substitute = re.sub(
|
||||
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?(-dev)?[0-9]*"',
|
||||
f'\nversion = "{new_version.to_string()}"',
|
||||
self.content,
|
||||
)
|
||||
self.content = substitute
|
||||
case BuildFileType.JAVA_CLOJURE:
|
||||
# TODO: we should stick here on defproject instead of first line!
|
||||
substitute = re.sub(
|
||||
'"[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"',
|
||||
f'"{new_version.to_string()}"',
|
||||
self.content,
|
||||
1,
|
||||
)
|
||||
self.content = substitute
|
||||
except:
|
||||
raise RuntimeError(f"Version not found in file {self.file_path}")
|
||||
raise Exception(f"Version not found in file {self.file_path}")
|
||||
|
||||
def get_default_suffix(self) -> str:
|
||||
result = "SNAPSHOT"
|
||||
|
|
|
@ -78,12 +78,6 @@ class DnsRecord(Validateable):
|
|||
result.append("ipv4 & ipv6 may not both be empty.")
|
||||
return result
|
||||
|
||||
def ip(self) -> str:
|
||||
if (self.ipv4):
|
||||
return self.ipv4
|
||||
else:
|
||||
return self.ipv6
|
||||
|
||||
|
||||
class Devops(Validateable):
|
||||
def __init__(
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from enum import Enum
|
||||
from typing import List, Dict
|
||||
from .common import (
|
||||
filter_none,
|
||||
|
@ -6,23 +5,15 @@ from .common import (
|
|||
)
|
||||
|
||||
|
||||
class NamingType(Enum):
|
||||
NAME_ONLY = 1
|
||||
NAME_AND_MODULE = 2
|
||||
|
||||
|
||||
class Image(Validateable):
|
||||
def __init__(
|
||||
self,
|
||||
inp: dict,
|
||||
):
|
||||
self.module = inp.get("module")
|
||||
self.name = inp.get("name")
|
||||
self.image_dockerhub_user = inp.get("image_dockerhub_user")
|
||||
self.image_dockerhub_password = inp.get("image_dockerhub_password")
|
||||
self.image_tag = inp.get("image_tag")
|
||||
self.image_build_commons_path = inp.get("image_build_commons_path")
|
||||
self.image_naming = NamingType[inp.get("image_naming", "NAME_ONLY")]
|
||||
self.image_use_package_common_files = inp.get(
|
||||
"image_use_package_common_files", True
|
||||
)
|
||||
|
@ -32,10 +23,8 @@ class Image(Validateable):
|
|||
|
||||
def validate(self) -> List[str]:
|
||||
result = []
|
||||
result += self.__validate_is_not_empty__("name")
|
||||
result += self.__validate_is_not_empty__("image_dockerhub_user")
|
||||
result += self.__validate_is_not_empty__("image_dockerhub_password")
|
||||
result += self.__validate_is_not_empty__("image_naming")
|
||||
if not self.image_use_package_common_files:
|
||||
result += self.__validate_is_not_empty__("image_build_commons_path")
|
||||
result += self.__validate_is_not_empty__("image_build_commons_dir_name")
|
||||
|
@ -48,16 +37,6 @@ class Image(Validateable):
|
|||
]
|
||||
return "/".join(filter_none(commons_path)) + "/"
|
||||
|
||||
def image_name(self) -> str:
|
||||
result: List[str] = [self.name] # type: ignore
|
||||
if (
|
||||
self.image_naming == NamingType.NAME_AND_MODULE
|
||||
and self.module
|
||||
and self.module != ""
|
||||
):
|
||||
result.append(self.module)
|
||||
return "-".join(result)
|
||||
|
||||
@classmethod
|
||||
def get_mapping_default(cls) -> List[Dict[str, str]]:
|
||||
return [
|
||||
|
|
|
@ -8,7 +8,7 @@ from .provider_digitalocean import Digitalocean
|
|||
from .provider_hetzner import Hetzner
|
||||
from .c4k import C4k
|
||||
from .image import Image
|
||||
from .release import ReleaseType, Release
|
||||
from .release import ReleaseType
|
||||
from ..infrastructure import BuildFileRepository, CredentialsApi, EnvironmentApi, GitApi
|
||||
|
||||
|
||||
|
@ -69,7 +69,6 @@ class InitService:
|
|||
Path(primary_build_file_id)
|
||||
)
|
||||
version = primary_build_file.get_version()
|
||||
default_mappings += Release.get_mapping_default()
|
||||
|
||||
credentials = Credentials(inp, default_mappings)
|
||||
authorization = self.authorization(credentials)
|
||||
|
@ -112,8 +111,9 @@ class InitService:
|
|||
result = {}
|
||||
for name in credentials.mappings.keys():
|
||||
mapping = credentials.mappings[name]
|
||||
if self.environment_api.is_defined(mapping.name_for_environment()):
|
||||
result[name] = self.environment_api.get(mapping.name_for_environment())
|
||||
env_value = self.environment_api.get(mapping.name_for_environment())
|
||||
if env_value:
|
||||
result[name] = env_value
|
||||
else:
|
||||
if mapping.gopass_type() == GopassType.FIELD:
|
||||
result[name] = self.credentials_api.gopass_field_from_path(
|
||||
|
|
|
@ -36,8 +36,6 @@ class Aws(Validateable, CredentialMappingDefault):
|
|||
result = {}
|
||||
if self.aws_as_backend:
|
||||
result = {
|
||||
"access_key": self.aws_access_key,
|
||||
"secret_key": self.aws_secret_key,
|
||||
"bucket": self.aws_bucket,
|
||||
"key": self.__bucket_key__(),
|
||||
"region": self.aws_region,
|
||||
|
|
|
@ -20,14 +20,6 @@ CONFIG_CERTMANAGER = """certmanager:
|
|||
"""
|
||||
CONFIG_ECHO = """echo: $echo
|
||||
"""
|
||||
CONFIG_HETZNER_CSI = """hetzner:
|
||||
hcloudApiToken:
|
||||
source: "PLAIN" # PLAIN, GOPASS or PROMPT
|
||||
parameter: $hcloud_api # the api key for the hetzner cloud
|
||||
encryptionPassphrase:
|
||||
source: "PLAIN" # PLAIN, GOPASS or PROMPT
|
||||
parameter: $encryption # the encryption passphrase for created volumes
|
||||
"""
|
||||
|
||||
|
||||
class K3s(Validateable):
|
||||
|
@ -36,11 +28,8 @@ class K3s(Validateable):
|
|||
self.k3s_letsencrypt_email = inp.get("k3s_letsencrypt_email")
|
||||
self.k3s_letsencrypt_endpoint = inp.get("k3s_letsencrypt_endpoint", "staging")
|
||||
self.k3s_app_filename_to_provision = inp.get("k3s_app_filename_to_provision")
|
||||
self.k3s_enable_echo = inp.get("k3s_enable_echo", None)
|
||||
self.k3s_enable_echo = inp.get("k3s_enable_echo", "false")
|
||||
self.k3s_provs_template = inp.get("k3s_provs_template", None)
|
||||
self.k3s_enable_hetzner_csi = inp.get("k3s_enable_hetzner_csi", False)
|
||||
self.k3s_hetzner_api_token = inp.get("k3s_hetzner_api_token", None)
|
||||
self.k3s_hetzner_encryption_passphrase = inp.get("k3s_hetzner_encryption_passphrase", None)
|
||||
self.provision_dns: Optional[DnsRecord] = None
|
||||
|
||||
def validate(self) -> List[str]:
|
||||
|
@ -48,9 +37,6 @@ class K3s(Validateable):
|
|||
result += self.__validate_is_not_empty__("k3s_letsencrypt_email")
|
||||
result += self.__validate_is_not_empty__("k3s_letsencrypt_endpoint")
|
||||
result += self.__validate_is_not_empty__("k3s_app_filename_to_provision")
|
||||
if self.k3s_enable_hetzner_csi:
|
||||
result += self.__validate_is_not_empty__("k3s_hetzner_api_token")
|
||||
result += self.__validate_is_not_empty__("k3s_hetzner_encryption_passphrase")
|
||||
if self.provision_dns:
|
||||
result += self.provision_dns.validate()
|
||||
return result
|
||||
|
@ -75,9 +61,6 @@ class K3s(Validateable):
|
|||
substitutes["letsencrypt_endpoint"] = self.k3s_letsencrypt_endpoint
|
||||
if self.k3s_enable_echo is not None:
|
||||
substitutes["echo"] = self.k3s_enable_echo
|
||||
if self.k3s_enable_hetzner_csi:
|
||||
substitutes["hcloud_api"] = self.k3s_hetzner_api_token
|
||||
substitutes["encryption"] = self.k3s_hetzner_encryption_passphrase
|
||||
return self.__config_template__().substitute(substitutes)
|
||||
|
||||
def command(self, devops: Devops):
|
||||
|
@ -86,7 +69,7 @@ class K3s(Validateable):
|
|||
cmd = [
|
||||
"provs-server.jar",
|
||||
"k3s",
|
||||
f"{self.k3s_provision_user}@{self.provision_dns.ip()}",
|
||||
f"{self.k3s_provision_user}@{self.provision_dns.fqdn}",
|
||||
"-c",
|
||||
f"{devops.build_path()}/out_k3sServerConfig.yaml",
|
||||
"-a",
|
||||
|
@ -106,6 +89,4 @@ class K3s(Validateable):
|
|||
template_text += CONFIG_IPV4
|
||||
if self.provision_dns.ipv6 is not None:
|
||||
template_text += CONFIG_IPV6
|
||||
if self.k3s_enable_hetzner_csi:
|
||||
template_text += CONFIG_HETZNER_CSI
|
||||
return Template(template_text)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional, List, Dict
|
||||
from typing import Optional, List
|
||||
from pathlib import Path
|
||||
from .common import (
|
||||
Validateable,
|
||||
|
@ -7,9 +7,6 @@ from .common import (
|
|||
from .version import (
|
||||
Version,
|
||||
)
|
||||
from .artifact import (
|
||||
Artifact,
|
||||
)
|
||||
|
||||
|
||||
class Release(Validateable):
|
||||
|
@ -24,14 +21,6 @@ class Release(Validateable):
|
|||
"release_secondary_build_files", []
|
||||
)
|
||||
self.version = version
|
||||
self.release_tag_prefix = inp.get("release_tag_prefix", "")
|
||||
self.release_artifact_server_url = inp.get("release_artifact_server_url")
|
||||
self.release_organisation = inp.get("release_organisation")
|
||||
self.release_repository_name = inp.get("release_repository_name")
|
||||
self.release_artifact_token = inp.get("release_artifact_token")
|
||||
self.release_artifacts = []
|
||||
for a in inp.get("release_artifacts", []):
|
||||
self.release_artifacts.append(Artifact(a))
|
||||
|
||||
def update_release_type(self, release_type: ReleaseType):
|
||||
self.release_type = release_type
|
||||
|
@ -64,44 +53,10 @@ class Release(Validateable):
|
|||
and self.release_type != ReleaseType.NONE
|
||||
and self.release_main_branch != self.release_current_branch
|
||||
):
|
||||
result.append(
|
||||
f"Releases are allowed only on {self.release_main_branch}"
|
||||
)
|
||||
return result
|
||||
|
||||
def validate_for_artifact(self):
|
||||
result = []
|
||||
result += self.__validate_is_not_empty__("release_artifact_server_url")
|
||||
result += self.__validate_is_not_empty__("release_organisation")
|
||||
result += self.__validate_is_not_empty__("release_repository_name")
|
||||
result += self.__validate_is_not_empty__("release_artifact_token")
|
||||
result.append(f"Releases are allowed only on {self.release_main_branch}")
|
||||
return result
|
||||
|
||||
def build_files(self) -> List[str]:
|
||||
result = [self.release_primary_build_file]
|
||||
result += self.release_secondary_build_files
|
||||
return result
|
||||
|
||||
def forgejo_release_api_endpoint(self) -> str:
|
||||
validation = self.validate_for_artifact()
|
||||
if validation != []:
|
||||
raise RuntimeError(f"not valid for creating artifacts: {validation}")
|
||||
|
||||
server_url = self.release_artifact_server_url.removeprefix("/").removesuffix(
|
||||
"/"
|
||||
)
|
||||
organisation = self.release_organisation.removeprefix("/").removesuffix("/")
|
||||
repository = self.release_repository_name.removeprefix("/").removesuffix("/")
|
||||
return f"{server_url}/api/v1/repos/{organisation}/{repository}/releases"
|
||||
|
||||
def forgejo_release_asset_api_endpoint(self, release_id: int) -> str:
|
||||
return f"{self.forgejo_release_api_endpoint()}/{release_id}/assets"
|
||||
|
||||
@classmethod
|
||||
def get_mapping_default(cls) -> List[Dict[str, str]]:
|
||||
return [
|
||||
{
|
||||
"gopass_path": "server/meissa/repo/buero-rw",
|
||||
"name": "release_artifact_token",
|
||||
}
|
||||
]
|
||||
|
|
|
@ -32,6 +32,12 @@ class Version(Validateable):
|
|||
self.snapshot_suffix = snapshot_suffix
|
||||
self.default_snapshot_suffix = default_snapshot_suffix
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.to_string() == other.to_string()
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self.to_string().__hash__()
|
||||
|
||||
def is_snapshot(self):
|
||||
return self.snapshot_suffix is not None
|
||||
|
||||
|
@ -133,9 +139,3 @@ class Version(Validateable):
|
|||
snapshot_suffix=None,
|
||||
version_str=None,
|
||||
)
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and self.to_string() == other.to_string()
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return self.to_string().__hash__()
|
||||
|
|
|
@ -7,6 +7,5 @@ from .infrastructure import (
|
|||
CredentialsApi,
|
||||
GitApi,
|
||||
TerraformApi,
|
||||
ArtifactDeploymentApi,
|
||||
)
|
||||
from .repository import DevopsRepository, BuildFileRepository
|
||||
|
|
|
@ -53,27 +53,37 @@ class ImageApi:
|
|||
self.execution_api = ExecutionApi()
|
||||
|
||||
def image(self, name: str, path: Path):
|
||||
self.execution_api.execute_live(
|
||||
self.execution_api.run_handled(
|
||||
f"docker build -t {name} --file {path}/image/Dockerfile {path}/image"
|
||||
)
|
||||
|
||||
def drun(self, name: str):
|
||||
self.execution_api.execute_live(
|
||||
f'docker run -it {name} /bin/bash'
|
||||
self.execution_api.run_handled(
|
||||
f'docker run -it --entrypoint="" {name} /bin/bash'
|
||||
)
|
||||
|
||||
def dockerhub_login(self, username: str, password: str):
|
||||
self.execution_api.execute_secure(
|
||||
f"docker login --username {username} --password {password}",
|
||||
"docker login --username ***** --password *****",
|
||||
self.execution_api.run_handled(
|
||||
f"docker login --username {username} --password {password}"
|
||||
)
|
||||
|
||||
def dockerhub_publish(self, name: str, username: str, tag: str):
|
||||
self.execution_api.execute_live(f"docker tag {name} {username}/{name}:{tag}")
|
||||
self.execution_api.execute_live(f"docker push {username}/{name}:{tag}")
|
||||
def dockerhub_publish(self, name: str, username: str, tag=None):
|
||||
if tag is not None:
|
||||
self.execution_api.run_handled(
|
||||
f"docker tag {name} {username}/{name}:{tag}"
|
||||
)
|
||||
self.execution_api.run_handled(
|
||||
f"docker push {username}/{name}:{tag}"
|
||||
)
|
||||
self.execution_api.run_handled(
|
||||
f"docker tag {name} {username}/{name}:latest"
|
||||
)
|
||||
self.execution_api.run_handled(
|
||||
f"docker push {username}/{name}:latest"
|
||||
)
|
||||
|
||||
def test(self, name: str, path: Path):
|
||||
self.execution_api.execute_live(
|
||||
self.execution_api.run_handled(
|
||||
f"docker build -t {name} -test --file {path}/test/Dockerfile {path}/test"
|
||||
)
|
||||
|
||||
|
@ -84,58 +94,40 @@ class ExecutionApi:
|
|||
if dry_run:
|
||||
print(command)
|
||||
else:
|
||||
try:
|
||||
# output = check_output(command, encoding="UTF-8", shell=shell)
|
||||
output = run(
|
||||
command,
|
||||
shell=shell,
|
||||
check=check,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
text=True,
|
||||
command, encoding="UTF-8", shell=shell, stdout=PIPE, check=check
|
||||
).stdout
|
||||
output = output.rstrip()
|
||||
except CalledProcessError as exc:
|
||||
print(
|
||||
f"Command failed with code: {exc.returncode} and message: {exc.stderr}"
|
||||
)
|
||||
raise exc
|
||||
return output
|
||||
|
||||
def execute_secure(
|
||||
self,
|
||||
command: str,
|
||||
sanitized_command: str,
|
||||
dry_run=False,
|
||||
shell=True,
|
||||
check=True,
|
||||
):
|
||||
try:
|
||||
output = self.execute(command, dry_run, shell, check)
|
||||
return output
|
||||
except CalledProcessError as exc:
|
||||
sanitized_exc = exc
|
||||
sanitized_exc.cmd = sanitized_command
|
||||
raise sanitized_exc
|
||||
|
||||
def execute_live(self, command: str, dry_run=False, shell=True):
|
||||
def execute_live(self, command, dry_run=False, shell=True):
|
||||
if dry_run:
|
||||
print(command)
|
||||
else:
|
||||
process = Popen(command, shell=shell)
|
||||
outs, errs = process.communicate()
|
||||
while outs is not None:
|
||||
stdout.buffer.write(outs)
|
||||
if process.returncode != 0:
|
||||
raise RuntimeError(f"Execute live '{command}' failed with code {process.returncode}\nerrs: {errs}")
|
||||
process = Popen(command, stdout=PIPE, shell=shell)
|
||||
for line in iter(process.stdout.readline, b""):
|
||||
print(line.decode("utf-8"), end="")
|
||||
process.stdout.close()
|
||||
process.wait()
|
||||
|
||||
def run_handled(self, command: str, shell=True, check=True):
|
||||
try:
|
||||
run(
|
||||
command,
|
||||
shell=shell,
|
||||
check=check,
|
||||
capture_output=True,
|
||||
text=True)
|
||||
except CalledProcessError as exc:
|
||||
print("Command failed with code: ", exc.returncode, " and message:", exc.stderr)
|
||||
|
||||
|
||||
|
||||
class EnvironmentApi:
|
||||
def get(self, key):
|
||||
return environ.get(key)
|
||||
|
||||
def is_defined(self, key):
|
||||
return key in environ
|
||||
|
||||
|
||||
class CredentialsApi:
|
||||
def __init__(self):
|
||||
|
@ -214,53 +206,3 @@ class GitApi:
|
|||
|
||||
class TerraformApi:
|
||||
pass
|
||||
|
||||
|
||||
class ArtifactDeploymentApi:
|
||||
def __init__(self):
|
||||
self.execution_api = ExecutionApi()
|
||||
|
||||
def create_forgejo_release(self, api_endpoint_url: str, tag: str, token: str):
|
||||
command = (
|
||||
f'curl -X "POST" "{api_endpoint_url}" '
|
||||
+ ' -H "accept: application/json" -H "Content-Type: application/json"'
|
||||
+ f' -d \'{{ "body": "Provides files for release {tag}", "tag_name": "{tag}"}}\''
|
||||
) # noqa: E501
|
||||
print(command + ' -H "Authorization: token xxxx"')
|
||||
return self.execution_api.execute_secure(
|
||||
command=command + f' -H "Authorization: token {token}"',
|
||||
sanitized_command=command + ' -H "Authorization: token xxxx"',
|
||||
)
|
||||
|
||||
def add_asset_to_release(
|
||||
self,
|
||||
api_endpoint_url: str,
|
||||
attachment: Path,
|
||||
attachment_type: str,
|
||||
token: str,
|
||||
):
|
||||
command = (
|
||||
f'curl -X "POST" "{api_endpoint_url}"'
|
||||
+ ' -H "accept: application/json"'
|
||||
+ ' -H "Content-Type: multipart/form-data"'
|
||||
+ f' -F "attachment=@{attachment};type={attachment_type}"'
|
||||
) # noqa: E501
|
||||
print(command + ' -H "Authorization: token xxxx"')
|
||||
return self.execution_api.execute_secure(
|
||||
command=command + f' -H "Authorization: token {token}"',
|
||||
sanitized_command=command + ' -H "Authorization: token xxxx"',
|
||||
)
|
||||
|
||||
def calculate_sha256(self, path: Path):
|
||||
shasum = f"{path}.sha256"
|
||||
self.execution_api.execute(
|
||||
f"sha256sum {path} > {shasum}",
|
||||
)
|
||||
return shasum
|
||||
|
||||
def calculate_sha512(self, path: Path):
|
||||
shasum = f"{path}.sha512"
|
||||
self.execution_api.execute(
|
||||
f"sha512sum {path} > {shasum}",
|
||||
)
|
||||
return shasum
|
||||
|
|
|
@ -26,8 +26,3 @@ class ReleaseMixin(DevopsBuild):
|
|||
devops = self.devops_repo.get_devops(self.project)
|
||||
release = devops.mixins[MixinType.RELEASE]
|
||||
self.release_service.tag_bump_and_push_release(release)
|
||||
|
||||
def publish_artifacts(self):
|
||||
devops = self.devops_repo.get_devops(self.project)
|
||||
release = devops.mixins[MixinType.RELEASE]
|
||||
self.release_service.publish_artifacts(release)
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
#
|
||||
#deprecated, we recommend to use install_functions_debian.sh instead. We will going to remove install_functions.sh in a future release.
|
||||
#
|
||||
function upgradeSystem() {
|
||||
{
|
||||
apt-get update
|
||||
apt-get -qqy upgrade
|
||||
} > /dev/null
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update > /dev/null
|
||||
apt-get -y install apt-utils > /dev/null
|
||||
apt-get -qqy dist-upgrade > /dev/null
|
||||
}
|
||||
|
||||
function cleanupDocker() {
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
function upgradeSystem() {
|
||||
apk -U upgrade
|
||||
}
|
||||
|
||||
function cleanupDocker() {
|
||||
rm -f /root/.ssh/authorized_keys
|
||||
rm -f /root/.ssh/authorized_keys2
|
||||
|
||||
apk cache clean
|
||||
|
||||
rm -rf /tmp/*
|
||||
|
||||
find /var/cache -type f -exec rm -rf {} \;
|
||||
find /var/log/ -name '*.log' -exec rm -f {} \;
|
||||
}
|
||||
|
||||
function cleanupAmi() {
|
||||
rm -f /home/ubuntu/.ssh/authorized_keys
|
||||
rm -f /home/ubuntu/.ssh/authorized_keys2
|
||||
cleanupDocker
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
function upgradeSystem() {
|
||||
apt-get update
|
||||
apt-get -qqy upgrade
|
||||
}
|
||||
|
||||
function cleanupDocker() {
|
||||
rm -f /root/.ssh/authorized_keys
|
||||
rm -f /root/.ssh/authorized_keys2
|
||||
|
||||
apt-get clean
|
||||
apt-get -qqy autoremove --purge
|
||||
apt-get -qqy autoclean
|
||||
rm -rf /var/lib/apt/lists/
|
||||
|
||||
rm -rf /tmp/*
|
||||
|
||||
find /var/cache -type f -exec rm -rf {} \;
|
||||
find /var/log/ -name '*.log' -exec rm -f {} \;
|
||||
}
|
||||
|
||||
function cleanupAmi() {
|
||||
rm -f /home/ubuntu/.ssh/authorized_keys
|
||||
rm -f /home/ubuntu/.ssh/authorized_keys2
|
||||
cleanupDocker
|
||||
}
|
|
@ -7,16 +7,12 @@ from src.main.python.ddadevops.domain import (
|
|||
from src.test.python.domain.helper import (
|
||||
BuildFileRepositoryMock,
|
||||
GitApiMock,
|
||||
ArtifactDeploymentApiMock,
|
||||
build_devops,
|
||||
)
|
||||
from src.main.python.ddadevops.application import ReleaseService
|
||||
|
||||
|
||||
def test_should_update_release_type():
|
||||
sut = ReleaseService(
|
||||
GitApiMock(), ArtifactDeploymentApiMock(), BuildFileRepositoryMock("build.py")
|
||||
)
|
||||
def test_sould_update_release_type():
|
||||
sut = ReleaseService(GitApiMock(), BuildFileRepositoryMock("build.py"))
|
||||
devops = build_devops({})
|
||||
release = devops.mixins[MixinType.RELEASE]
|
||||
sut.update_release_type(release, "MAJOR")
|
||||
|
@ -24,40 +20,3 @@ def test_should_update_release_type():
|
|||
|
||||
with pytest.raises(Exception):
|
||||
sut.update_release_type(release, "NOT_EXISTING")
|
||||
|
||||
|
||||
def test_should_publish_artifacts():
|
||||
mock = ArtifactDeploymentApiMock(release='{"id": 2345}')
|
||||
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||
devops = build_devops(
|
||||
{
|
||||
"release_artifacts": ["target/art"],
|
||||
"release_artifact_server_url": "http://repo.test/",
|
||||
"release_organisation": "orga",
|
||||
"release_repository_name": "repo",
|
||||
}
|
||||
)
|
||||
release = devops.mixins[MixinType.RELEASE]
|
||||
sut.publish_artifacts(release)
|
||||
assert "http://repo.test/api/v1/repos/orga/repo/releases/2345/assets" == mock.add_asset_to_release_api_endpoint
|
||||
|
||||
def test_should_throw_exception_if_there_was_an_error_in_publish_artifacts():
|
||||
devops = build_devops(
|
||||
{
|
||||
"release_artifacts": ["target/art"],
|
||||
"release_artifact_server_url": "http://repo.test/",
|
||||
"release_organisation": "orga",
|
||||
"release_repository_name": "repo",
|
||||
}
|
||||
)
|
||||
release = devops.mixins[MixinType.RELEASE]
|
||||
|
||||
with pytest.raises(Exception):
|
||||
mock = ArtifactDeploymentApiMock(release='')
|
||||
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||
sut.publish_artifacts(release)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
mock = ArtifactDeploymentApiMock(release='{"message": "there was an error", "url":"some-url"}')
|
||||
sut = ReleaseService(GitApiMock(), mock, BuildFileRepositoryMock())
|
||||
sut.publish_artifacts(release)
|
||||
|
|
|
@ -53,11 +53,6 @@ def devops_config(overrides: dict) -> dict:
|
|||
"release_current_branch": "my_feature",
|
||||
"release_primary_build_file": "./package.json",
|
||||
"release_secondary_build_file": [],
|
||||
"release_artifacts": [],
|
||||
"release_artifact_token": "release_artifact_token",
|
||||
"release_artifact_server_url": None,
|
||||
"release_organisation": None,
|
||||
"release_repository_name": None,
|
||||
"credentials_mappings": [
|
||||
{
|
||||
"gopass_path": "a/path",
|
||||
|
@ -104,9 +99,6 @@ class EnvironmentApiMock:
|
|||
def get(self, key):
|
||||
return self.mappings.get(key, None)
|
||||
|
||||
def is_defined(self, key):
|
||||
return key in self.mappings
|
||||
|
||||
|
||||
class CredentialsApiMock:
|
||||
def __init__(self, mappings):
|
||||
|
@ -156,33 +148,5 @@ class GitApiMock:
|
|||
def push(self):
|
||||
pass
|
||||
|
||||
def push_follow_tags(self):
|
||||
pass
|
||||
|
||||
def checkout(self, branch: str):
|
||||
pass
|
||||
|
||||
|
||||
class ArtifactDeploymentApiMock:
|
||||
def __init__(self, release=""):
|
||||
self.release = release
|
||||
self.create_forgejo_release_count = 0
|
||||
self.add_asset_to_release_count = 0
|
||||
self.add_asset_to_release_api_endpoint = ""
|
||||
|
||||
def create_forgejo_release(self, api_endpoint: str, tag: str, token: str):
|
||||
self.create_forgejo_release_count += 1
|
||||
return self.release
|
||||
|
||||
def add_asset_to_release(
|
||||
self, api_endpoint: str, attachment: str, attachment_type: str, token: str
|
||||
):
|
||||
self.add_asset_to_release_api_endpoint = api_endpoint
|
||||
self.add_asset_to_release_count += 1
|
||||
pass
|
||||
|
||||
def calculate_sha256(self, path: Path):
|
||||
return f"{path}.sha256"
|
||||
|
||||
def calculate_sha512(self, path: Path):
|
||||
return f"{path}.sha512"
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import pytest
|
||||
from pybuilder.core import Project
|
||||
from pathlib import Path
|
||||
from src.main.python.ddadevops.domain import (
|
||||
Validateable,
|
||||
DnsRecord,
|
||||
Devops,
|
||||
BuildType,
|
||||
MixinType,
|
||||
Artifact,
|
||||
Image,
|
||||
)
|
||||
from .helper import build_devops, devops_config
|
||||
|
||||
|
||||
def test_should_validate_release():
|
||||
sut = Artifact("x")
|
||||
assert sut.is_valid()
|
||||
|
||||
sut = Artifact(None)
|
||||
assert not sut.is_valid()
|
||||
|
||||
def test_should_calculate_type():
|
||||
sut = Artifact("x.jar")
|
||||
assert "application/x-java-archive" == sut.type()
|
||||
|
||||
sut = Artifact("x.js")
|
||||
assert "application/x-javascript" == sut.type()
|
||||
|
||||
sut = Artifact("x.jar.sha256")
|
||||
assert "text/plain" == sut.type()
|
||||
|
|
@ -7,7 +7,7 @@ from src.main.python.ddadevops.domain import (
|
|||
)
|
||||
|
||||
|
||||
def test_should_validate_build_file():
|
||||
def test_sould_validate_build_file():
|
||||
sut = BuildFile(Path("./project.clj"), "content")
|
||||
assert sut.is_valid()
|
||||
|
||||
|
@ -18,7 +18,7 @@ def test_should_validate_build_file():
|
|||
assert not sut.is_valid()
|
||||
|
||||
|
||||
def test_should_calculate_build_type():
|
||||
def test_sould_calculate_build_type():
|
||||
sut = BuildFile(Path("./project.clj"), "content")
|
||||
assert sut.build_file_type() == BuildFileType.JAVA_CLOJURE
|
||||
|
||||
|
@ -29,7 +29,7 @@ def test_should_calculate_build_type():
|
|||
assert sut.build_file_type() == BuildFileType.JS
|
||||
|
||||
|
||||
def test_should_parse_and_set_js():
|
||||
def test_sould_parse_and_set_js():
|
||||
sut = BuildFile(
|
||||
Path("./package.json"),
|
||||
"""
|
||||
|
@ -77,7 +77,7 @@ def test_should_parse_and_set_js():
|
|||
)
|
||||
|
||||
|
||||
def test_should_parse_and_set_version_for_gradle():
|
||||
def test_sould_parse_and_set_version_for_gradle():
|
||||
sut = BuildFile(
|
||||
Path("./build.gradle"),
|
||||
"""
|
||||
|
@ -97,7 +97,7 @@ version = "1.1.5-SNAPSHOT"
|
|||
assert '\nversion = "2.0.0"\n' == sut.content
|
||||
|
||||
|
||||
def test_should_parse_and_set_version_for_py():
|
||||
def test_sould_parse_and_set_version_for_py():
|
||||
sut = BuildFile(
|
||||
Path("./build.py"),
|
||||
"""
|
||||
|
@ -143,7 +143,7 @@ version = "1.1.5-SNAPSHOT"
|
|||
assert '\nversion = "2.0.0"\n' == sut.content
|
||||
|
||||
|
||||
def test_should_parse_and_set_version_for_clj():
|
||||
def test_sould_parse_and_set_version_for_clj():
|
||||
sut = BuildFile(
|
||||
Path("./project.clj"),
|
||||
"""
|
||||
|
@ -182,71 +182,3 @@ def test_should_parse_and_set_version_for_clj():
|
|||
'\n(defproject org.domaindrivenarchitecture/c4k-jira "2.0.0"\n:dependencies [[org.clojure/clojure "1.11.0"]]\n)\n '
|
||||
== sut.content
|
||||
)
|
||||
|
||||
def test_should_parse_and_set_version_for_clj_edn():
|
||||
sut = BuildFile(
|
||||
Path("./deps.edn"),
|
||||
"""
|
||||
{:project {:name org.domaindrivenarchitecture/dda-backup
|
||||
:version "1.1.5-SNAPSHOT"}
|
||||
|
||||
}
|
||||
""",
|
||||
)
|
||||
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
|
||||
|
||||
sut = BuildFile(
|
||||
Path("./deps.edn"),
|
||||
"""
|
||||
{:project {:name org.domaindrivenarchitecture/dda-backup
|
||||
:version "1.1.5-SNAPSHOT"}
|
||||
|
||||
}
|
||||
""",
|
||||
)
|
||||
sut.set_version(Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT").create_major())
|
||||
assert (
|
||||
'\n{:project {:name org.domaindrivenarchitecture/dda-backup\n :version "2.0.0"}\n\n}\n'
|
||||
== sut.content
|
||||
)
|
||||
|
||||
|
||||
def test_should_throw_for_clj_wrong_version():
|
||||
sut = BuildFile(
|
||||
Path("./project.clj"),
|
||||
"""
|
||||
(defproject org.domaindrivenarchitecture/c4k-jira "1.1.5-Snapshot"
|
||||
:description "jira c4k-installation package"
|
||||
:url "https://domaindrivenarchitecture.org"
|
||||
)
|
||||
""",
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError):
|
||||
sut.get_version()
|
||||
|
||||
def test_should_ignore_first_version_for_py():
|
||||
sut = BuildFile(
|
||||
Path("./build.py"),
|
||||
"""
|
||||
from pybuilder.core import init, use_plugin, Author
|
||||
use_plugin("python.core")
|
||||
|
||||
name = "ddadevops"
|
||||
project_version = "0.0.2-dev1"
|
||||
version = "1.1.5-dev12"
|
||||
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
|
||||
""",
|
||||
)
|
||||
assert sut.get_version() == Version.from_str("1.1.5-dev12", "dev")
|
||||
|
||||
def test_should_ignore_first_version_for_gradle():
|
||||
sut = BuildFile(
|
||||
Path("./build.gradle"),
|
||||
"""
|
||||
kotlin_version = "3.3.3"
|
||||
version = "1.1.5-SNAPSHOT"
|
||||
|
||||
""",
|
||||
)
|
||||
assert sut.get_version() == Version.from_str("1.1.5-SNAPSHOT", "SNAPSHOT")
|
|
@ -4,11 +4,10 @@ from src.main.python.ddadevops.domain import (
|
|||
Version,
|
||||
BuildType,
|
||||
MixinType,
|
||||
Artifact,
|
||||
)
|
||||
|
||||
|
||||
def test_devops_creation():
|
||||
def test_devops_factory():
|
||||
with pytest.raises(Exception):
|
||||
DevopsFactory().build_devops({"build_types": ["NOTEXISTING"]})
|
||||
|
||||
|
@ -51,7 +50,6 @@ def test_devops_creation():
|
|||
assert sut is not None
|
||||
assert sut.specialized_builds[BuildType.C4K] is not None
|
||||
|
||||
def test_release_devops_creation():
|
||||
sut = DevopsFactory().build_devops(
|
||||
{
|
||||
"stage": "test",
|
||||
|
@ -68,32 +66,3 @@ def test_release_devops_creation():
|
|||
)
|
||||
assert sut is not None
|
||||
assert sut.mixins[MixinType.RELEASE] is not None
|
||||
|
||||
sut = DevopsFactory().build_devops(
|
||||
{
|
||||
"stage": "test",
|
||||
"name": "mybuild",
|
||||
"module": "test_image",
|
||||
"project_root_path": "../../..",
|
||||
"build_types": [],
|
||||
"mixin_types": ["RELEASE"],
|
||||
"release_main_branch": "main",
|
||||
"release_current_branch": "my_feature",
|
||||
"release_config_file": "project.clj",
|
||||
"release_artifacts": ["x.jar"],
|
||||
"release_artifact_token": "y",
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": "meissa",
|
||||
"release_repository_name": "provs",
|
||||
},
|
||||
Version.from_str("1.0.0", "SNAPSHOT"),
|
||||
)
|
||||
|
||||
release = sut.mixins[MixinType.RELEASE]
|
||||
assert release is not None
|
||||
assert Artifact("x.jar") == release.release_artifacts[0]
|
||||
|
||||
|
||||
def test_on_merge_input_should_win():
|
||||
sut = DevopsFactory()
|
||||
assert {'tag': 'inp'} == sut.merge(inp = {'tag': 'inp'}, context = {'tag': 'context'}, authorization={})
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
from pybuilder.core import Project
|
||||
import logging
|
||||
from subprocess import Popen, PIPE, run
|
||||
from pathlib import Path
|
||||
from src.main.python.ddadevops.domain import (
|
||||
BuildType,
|
||||
|
@ -12,16 +14,3 @@ def test_devops_build_commons_path():
|
|||
assert image is not None
|
||||
assert image.is_valid()
|
||||
assert "docker/" == image.build_commons_path()
|
||||
|
||||
def test_should_calculate_image_name():
|
||||
sut = build_devops({})
|
||||
image = sut.specialized_builds[BuildType.IMAGE]
|
||||
assert "name" == image.image_name()
|
||||
|
||||
sut = build_devops({'image_naming': "NAME_ONLY"})
|
||||
image = sut.specialized_builds[BuildType.IMAGE]
|
||||
assert "name" == image.image_name()
|
||||
|
||||
sut = build_devops({'image_naming': "NAME_AND_MODULE"})
|
||||
image = sut.specialized_builds[BuildType.IMAGE]
|
||||
assert "name-module" == image.image_name()
|
||||
|
|
|
@ -41,8 +41,6 @@ def test_should_calculate_backend_config():
|
|||
{
|
||||
"module": "dns_aws",
|
||||
"stage": "prod",
|
||||
"aws_access_key": "aws_access_key",
|
||||
"aws_secret_key": "aws_secret_key",
|
||||
"aws_bucket": "meissa-configuration",
|
||||
"aws_bucket_kms_key_id": "arn:aws:kms:eu-central-1:907507348333:alias/meissa-configuration",
|
||||
"aws_region": "eu-central-1",
|
||||
|
@ -50,8 +48,6 @@ def test_should_calculate_backend_config():
|
|||
)
|
||||
)
|
||||
assert {
|
||||
"access_key": "aws_access_key",
|
||||
"secret_key": "aws_secret_key",
|
||||
"bucket": "meissa-configuration",
|
||||
"key": "prod/dns_aws",
|
||||
"kms_key_id": "arn:aws:kms:eu-central-1:907507348333:alias/meissa-configuration",
|
||||
|
|
|
@ -24,7 +24,7 @@ def test_should_calculate_command():
|
|||
assert (
|
||||
"provs-server.jar "
|
||||
+ "k3s "
|
||||
+ "k3s_provision_user@::1 "
|
||||
+ "k3s_provision_user@example.org "
|
||||
+ "-c "
|
||||
+ "root_path/target/name/module/out_k3sServerConfig.yaml "
|
||||
+ "-a "
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import pytest
|
||||
from pybuilder.core import Project
|
||||
from pathlib import Path
|
||||
from src.main.python.ddadevops.domain import (
|
||||
|
@ -15,7 +14,7 @@ from src.main.python.ddadevops.domain import (
|
|||
from .helper import build_devops, devops_config
|
||||
|
||||
|
||||
def test_should_validate_release():
|
||||
def test_sould_validate_release():
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
|
@ -49,7 +48,7 @@ def test_should_validate_release():
|
|||
assert not sut.is_valid()
|
||||
|
||||
|
||||
def test_should_calculate_build_files():
|
||||
def test_sould_calculate_build_files():
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
|
@ -62,74 +61,3 @@ def test_should_calculate_build_files():
|
|||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||
)
|
||||
assert ["project.clj", "package.json"] == sut.build_files()
|
||||
|
||||
|
||||
def test_should_calculate_forgejo_release_api_endpoint():
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
"release_artifacts": [],
|
||||
"release_artifact_token": "y",
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": "meissa",
|
||||
"release_repository_name": "provs",
|
||||
}
|
||||
),
|
||||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||
)
|
||||
assert (
|
||||
"https://repo.prod.meissa.de/api/v1/repos/meissa/provs/releases"
|
||||
== sut.forgejo_release_api_endpoint()
|
||||
)
|
||||
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
"release_artifacts": ["x"],
|
||||
"release_artifact_token": "y",
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de/",
|
||||
"release_organisation": "/meissa/",
|
||||
"release_repository_name": "provs",
|
||||
}
|
||||
),
|
||||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||
)
|
||||
assert (
|
||||
"https://repo.prod.meissa.de/api/v1/repos/meissa/provs/releases"
|
||||
== sut.forgejo_release_api_endpoint()
|
||||
)
|
||||
assert(
|
||||
"/meissa/"
|
||||
== sut.release_organisation
|
||||
)
|
||||
|
||||
with pytest.raises(Exception):
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": None,
|
||||
"release_repository_name": "provs",
|
||||
}
|
||||
),
|
||||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||
)
|
||||
sut.forgejo_release_api_endpoint()
|
||||
|
||||
def test_should_calculate_forgejo_release_asset_api_endpoint():
|
||||
sut = Release(
|
||||
devops_config(
|
||||
{
|
||||
"release_artifacts": ["x"],
|
||||
"release_artifact_token": "y",
|
||||
"release_artifact_server_url": "https://repo.prod.meissa.de",
|
||||
"release_organisation": "meissa",
|
||||
"release_repository_name": "provs",
|
||||
}
|
||||
),
|
||||
Version.from_str("1.3.1-SNAPSHOT", "SNAPSHOT"),
|
||||
)
|
||||
assert (
|
||||
"https://repo.prod.meissa.de/api/v1/repos/meissa/provs/releases/123/assets"
|
||||
== sut.forgejo_release_asset_api_endpoint(123)
|
||||
)
|
||||
|
|
|
@ -5,9 +5,7 @@ from pybuilder.core import Project
|
|||
|
||||
from src.main.python.ddadevops.release_mixin import ReleaseMixin
|
||||
from src.main.python.ddadevops.domain import Devops, Release
|
||||
from src.main.python.ddadevops.application import ReleaseService
|
||||
from src.main.python.ddadevops.infrastructure import BuildFileRepository
|
||||
from .domain.helper import devops_config, GitApiMock, ArtifactDeploymentApiMock
|
||||
from .domain.helper import devops_config
|
||||
from .resource_helper import copy_resource
|
||||
|
||||
|
||||
|
@ -16,8 +14,6 @@ def test_release_mixin(tmp_path):
|
|||
copy_resource(Path("package.json"), tmp_path)
|
||||
project = Project(str_tmp_path, name="name")
|
||||
|
||||
os.environ["RELEASE_ARTIFACT_TOKEN"] = "ratoken"
|
||||
|
||||
sut = ReleaseMixin(
|
||||
project,
|
||||
devops_config(
|
||||
|
@ -32,37 +28,3 @@ def test_release_mixin(tmp_path):
|
|||
|
||||
sut.initialize_build_dir()
|
||||
assert sut.build_path() == f"{str_tmp_path}/target/name/release-test"
|
||||
|
||||
def test_release_mixin_different_version_suffixes(tmp_path):
|
||||
str_tmp_path = str(tmp_path)
|
||||
copy_resource(Path("config.py"), tmp_path)
|
||||
copy_resource(Path("config.gradle"), tmp_path)
|
||||
|
||||
project = Project(str_tmp_path, name="name")
|
||||
|
||||
os.environ["RELEASE_ARTIFACT_TOKEN"] = "ratoken"
|
||||
|
||||
sut = ReleaseMixin(
|
||||
project,
|
||||
devops_config(
|
||||
{
|
||||
"project_root_path": str_tmp_path,
|
||||
"mixin_types": ["RELEASE"],
|
||||
"build_types": [],
|
||||
"module": "release-test",
|
||||
"release_current_branch": "main",
|
||||
"release_main_branch": "main",
|
||||
"release_primary_build_file": "config.py",
|
||||
"release_secondary_build_files": ["config.gradle"],
|
||||
}
|
||||
),
|
||||
)
|
||||
sut.release_service = ReleaseService(GitApiMock(), ArtifactDeploymentApiMock(), BuildFileRepository(project.basedir))
|
||||
|
||||
sut.initialize_build_dir()
|
||||
sut.update_release_type("PATCH")
|
||||
sut.prepare_release()
|
||||
sut.tag_bump_and_push_release()
|
||||
|
||||
assert sut.release_service.build_file_repository.get(Path("config.py")).get_version().to_string() == "3.1.5-dev"
|
||||
assert sut.release_service.build_file_repository.get(Path("config.gradle")).get_version().to_string() == "3.1.5-SNAPSHOT"
|
Loading…
Reference in a new issue