ichec-cicd 0.1.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ichec_cicd-0.1.12/LICENSE +21 -0
- ichec_cicd-0.1.12/PKG-INFO +117 -0
- ichec_cicd-0.1.12/README.md +92 -0
- ichec_cicd-0.1.12/pyproject.toml +84 -0
- ichec_cicd-0.1.12/setup.cfg +4 -0
- ichec_cicd-0.1.12/src/ichec_cicd/__init__.py +0 -0
- ichec_cicd-0.1.12/src/ichec_cicd/__version__.py +1 -0
- ichec_cicd-0.1.12/src/ichec_cicd/ci/__init__.py +1 -0
- ichec_cicd-0.1.12/src/ichec_cicd/ci/ci.py +91 -0
- ichec_cicd-0.1.12/src/ichec_cicd/ci/cli.py +110 -0
- ichec_cicd-0.1.12/src/ichec_cicd/container/__init__.py +0 -0
- ichec_cicd-0.1.12/src/ichec_cicd/container/cli.py +61 -0
- ichec_cicd-0.1.12/src/ichec_cicd/container/container.py +27 -0
- ichec_cicd-0.1.12/src/ichec_cicd/main_cli.py +62 -0
- ichec_cicd-0.1.12/src/ichec_cicd/manifest/__init__.py +1 -0
- ichec_cicd-0.1.12/src/ichec_cicd/manifest/manifest.py +60 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/__init__.py +3 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/angular.py +29 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/cli.py +134 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/django.py +259 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/fastapi.py +68 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/python.py +52 -0
- ichec_cicd-0.1.12/src/ichec_cicd/packaging/wrapping.py +143 -0
- ichec_cicd-0.1.12/src/ichec_cicd/py.typed +0 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/__init__.py +2 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/cli.py +123 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/python_repo/__init__.py +1 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/python_repo/pyproject.py +40 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/python_repo/python_repo.py +52 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/python_repo/sphinx.py +32 -0
- ichec_cicd-0.1.12/src/ichec_cicd/repo/repo.py +48 -0
- ichec_cicd-0.1.12/src/ichec_cicd/version_control/__init__.py +0 -0
- ichec_cicd-0.1.12/src/ichec_cicd/version_control/merge_request.py +10 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/PKG-INFO +117 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/SOURCES.txt +39 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/dependency_links.txt +1 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/entry_points.txt +2 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/requires.txt +5 -0
- ichec_cicd-0.1.12/src/ichec_cicd.egg-info/top_level.txt +1 -0
- ichec_cicd-0.1.12/tests/test_bump_version.py +44 -0
- ichec_cicd-0.1.12/tests/test_django_wrapper.py +14 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Irish Centre for High End Computing
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ichec_cicd
|
|
3
|
+
Version: 0.1.12
|
|
4
|
+
Summary: A collection of utilities to manage ICHEC project CI/CD pipelines.
|
|
5
|
+
Author: Irish Centre for High End Computing
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://git.ichec.ie/platform-engineering/modules/cicd/ichec-cicd
|
|
8
|
+
Project-URL: Homepage, https://git.ichec.ie/platform-engineering/modules/cicd/ichec-cicd
|
|
9
|
+
Keywords: CICD,HPC,Gitlab
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
16
|
+
Requires-Python: >=3.14
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: build
|
|
20
|
+
Requires-Dist: twine
|
|
21
|
+
Requires-Dist: ichec_platform_core>=0.0.4
|
|
22
|
+
Requires-Dist: tomlkit
|
|
23
|
+
Requires-Dist: Jinja2
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# ichec_cicd
|
|
27
|
+
|
|
28
|
+
This project is a collection of utilities for managing CI/CD pipelines at ICHEC.
|
|
29
|
+
|
|
30
|
+
It provides opinionated interfaces to encourage standarization of our project structures and workflows.
|
|
31
|
+
|
|
32
|
+
# Install
|
|
33
|
+
|
|
34
|
+
The package is available from PyPI:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
pip install ichec_cicd
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
# Features #
|
|
41
|
+
|
|
42
|
+
## Deploy a Package to a Repository
|
|
43
|
+
|
|
44
|
+
From the package's top-level directory:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
ichec_cicd deploy --token $REPO_TOKEN
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
As an example, for a Python project this might be the PyPI repository's token.
|
|
51
|
+
|
|
52
|
+
## Set a Package's Version Number
|
|
53
|
+
|
|
54
|
+
From the package's top-level directory:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
ichec_cicd set_version $VERSION
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Increment a Repository's Tag ##
|
|
61
|
+
|
|
62
|
+
From the repository's top-level directory, and on the branch the tag will be dervied from:
|
|
63
|
+
|
|
64
|
+
``` sh
|
|
65
|
+
ichec_cicd increment_tag --field patch
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Here `semver` tag versioning is assumed with a `major.minor.patch` scheme. Note: in a CI/CD pipeline some more input options are needed to initialize the git repo for pushing the tag to. You can use the `--help` flag for more details.
|
|
69
|
+
|
|
70
|
+
## Sync Content With an External Upstream ##
|
|
71
|
+
|
|
72
|
+
Here we pull content from an external upstream repository and use it to update the content in a local repo. This can be useful for public mirrors that include a subset of the content in an internal repo.
|
|
73
|
+
|
|
74
|
+
``` sh
|
|
75
|
+
ichec_cicd sync_external_archive \
|
|
76
|
+
--source_token $SOURCE_TOKEN \
|
|
77
|
+
--project_id $SOURCE_PROJ_ID \
|
|
78
|
+
--sync_script $MY_SYNC_SCRIPT \
|
|
79
|
+
--asset_name $ASSET_NAME \
|
|
80
|
+
--archive_name $ARCHIVE_NAME \
|
|
81
|
+
--target_token $TARGET_TOKEN
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The inputs are:
|
|
85
|
+
|
|
86
|
+
* `SOURCE_TOKEN`: Gitlab access token for the source (private) repo - must have asset download rights
|
|
87
|
+
* `SOURCE_PROJ_ID`: The numeric project ID for the source repo
|
|
88
|
+
* `MY_SYNC_SCRIPT`: Path to a script that will use the extracted contents of the source archive to update the target repo
|
|
89
|
+
* `ASSET_NAME`: Name of the asset corresponding to the archive in the source repo's latest release collection
|
|
90
|
+
* `ARCHIVE_NAME`: Name of the downloaded file corresponding to the archive - this can differ from the asset name.
|
|
91
|
+
* `TARGET_TOKEN`: OATH token for the target repo - so that it can be pushed to from a CI runner
|
|
92
|
+
|
|
93
|
+
## Generate a containerfile ##
|
|
94
|
+
|
|
95
|
+
Here we generate a containerfile from a template given a release manifest in a repo:
|
|
96
|
+
|
|
97
|
+
``` sh
|
|
98
|
+
ichec_cicd containerfile generate --manifest <path_to_manifest> --template_dir <container_templates>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
where `<path_to_manifest>` is the path to an ICHEC release manifest and `<container_template>` is a directory with container templates.
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
## Containerize a Web App ##
|
|
105
|
+
|
|
106
|
+
Here we set up a standardized container build context for web applications, i.e. Django or FastAPI apps.
|
|
107
|
+
|
|
108
|
+
``` sh
|
|
109
|
+
ichec_cicd wrap --project <project_to_wrap> --template <wrapping_template>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
where `<project_to_wrap>` is a url or filesystem path to a repository with the project to be wrapped and `<wrapping_template>` is a url or path to a repository with a template to do the wrapping. The project to be wrapped needs to have an `ichec_manifest.yml` file at its top level with package metadata and the `<wrapping_template>` should match the framework being used, e.g. (Django/FastAPI).
|
|
113
|
+
|
|
114
|
+
# Licensing #
|
|
115
|
+
|
|
116
|
+
This project is licensed under the MIT License. See the accompanying `LICENSE` file for details.
|
|
117
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# ichec_cicd
|
|
2
|
+
|
|
3
|
+
This project is a collection of utilities for managing CI/CD pipelines at ICHEC.
|
|
4
|
+
|
|
5
|
+
It provides opinionated interfaces to encourage standarization of our project structures and workflows.
|
|
6
|
+
|
|
7
|
+
# Install
|
|
8
|
+
|
|
9
|
+
The package is available from PyPI:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pip install ichec_cicd
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
# Features #
|
|
16
|
+
|
|
17
|
+
## Deploy a Package to a Repository
|
|
18
|
+
|
|
19
|
+
From the package's top-level directory:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
ichec_cicd deploy --token $REPO_TOKEN
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
As an example, for a Python project this might be the PyPI repository's token.
|
|
26
|
+
|
|
27
|
+
## Set a Package's Version Number
|
|
28
|
+
|
|
29
|
+
From the package's top-level directory:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
ichec_cicd set_version $VERSION
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Increment a Repository's Tag ##
|
|
36
|
+
|
|
37
|
+
From the repository's top-level directory, and on the branch the tag will be dervied from:
|
|
38
|
+
|
|
39
|
+
``` sh
|
|
40
|
+
ichec_cicd increment_tag --field patch
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Here `semver` tag versioning is assumed with a `major.minor.patch` scheme. Note: in a CI/CD pipeline some more input options are needed to initialize the git repo for pushing the tag to. You can use the `--help` flag for more details.
|
|
44
|
+
|
|
45
|
+
## Sync Content With an External Upstream ##
|
|
46
|
+
|
|
47
|
+
Here we pull content from an external upstream repository and use it to update the content in a local repo. This can be useful for public mirrors that include a subset of the content in an internal repo.
|
|
48
|
+
|
|
49
|
+
``` sh
|
|
50
|
+
ichec_cicd sync_external_archive \
|
|
51
|
+
--source_token $SOURCE_TOKEN \
|
|
52
|
+
--project_id $SOURCE_PROJ_ID \
|
|
53
|
+
--sync_script $MY_SYNC_SCRIPT \
|
|
54
|
+
--asset_name $ASSET_NAME \
|
|
55
|
+
--archive_name $ARCHIVE_NAME \
|
|
56
|
+
--target_token $TARGET_TOKEN
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The inputs are:
|
|
60
|
+
|
|
61
|
+
* `SOURCE_TOKEN`: Gitlab access token for the source (private) repo - must have asset download rights
|
|
62
|
+
* `SOURCE_PROJ_ID`: The numeric project ID for the source repo
|
|
63
|
+
* `MY_SYNC_SCRIPT`: Path to a script that will use the extracted contents of the source archive to update the target repo
|
|
64
|
+
* `ASSET_NAME`: Name of the asset corresponding to the archive in the source repo's latest release collection
|
|
65
|
+
* `ARCHIVE_NAME`: Name of the downloaded file corresponding to the archive - this can differ from the asset name.
|
|
66
|
+
* `TARGET_TOKEN`: OATH token for the target repo - so that it can be pushed to from a CI runner
|
|
67
|
+
|
|
68
|
+
## Generate a containerfile ##
|
|
69
|
+
|
|
70
|
+
Here we generate a containerfile from a template given a release manifest in a repo:
|
|
71
|
+
|
|
72
|
+
``` sh
|
|
73
|
+
ichec_cicd containerfile generate --manifest <path_to_manifest> --template_dir <container_templates>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
where `<path_to_manifest>` is the path to an ICHEC release manifest and `<container_template>` is a directory with container templates.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Containerize a Web App ##
|
|
80
|
+
|
|
81
|
+
Here we set up a standardized container build context for web applications, i.e. Django or FastAPI apps.
|
|
82
|
+
|
|
83
|
+
``` sh
|
|
84
|
+
ichec_cicd wrap --project <project_to_wrap> --template <wrapping_template>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
where `<project_to_wrap>` is a url or filesystem path to a repository with the project to be wrapped and `<wrapping_template>` is a url or path to a repository with a template to do the wrapping. The project to be wrapped needs to have an `ichec_manifest.yml` file at its top level with package metadata and the `<wrapping_template>` should match the framework being used, e.g. (Django/FastAPI).
|
|
88
|
+
|
|
89
|
+
# Licensing #
|
|
90
|
+
|
|
91
|
+
This project is licensed under the MIT License. See the accompanying `LICENSE` file for details.
|
|
92
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ichec_cicd"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
license = { text = "MIT" }
|
|
5
|
+
authors = [
|
|
6
|
+
{ name="Irish Centre for High End Computing"},
|
|
7
|
+
]
|
|
8
|
+
description = "A collection of utilities to manage ICHEC project CI/CD pipelines."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.14"
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Development Status :: 3 - Alpha",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3.14",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Topic :: System :: Distributed Computing"
|
|
18
|
+
]
|
|
19
|
+
keywords = ["CICD", "HPC", "Gitlab"]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"build",
|
|
22
|
+
"twine",
|
|
23
|
+
"ichec_platform_core>=0.0.4",
|
|
24
|
+
"tomlkit",
|
|
25
|
+
"Jinja2",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Repository = "https://git.ichec.ie/platform-engineering/modules/cicd/ichec-cicd"
|
|
30
|
+
Homepage = "https://git.ichec.ie/platform-engineering/modules/cicd/ichec-cicd"
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
ichec_cicd = "ichec_cicd.main_cli:main_cli"
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["setuptools>=64", "setuptools-scm>=8"]
|
|
37
|
+
build-backend = "setuptools.build_meta"
|
|
38
|
+
|
|
39
|
+
# Version derived from the git tag (setuptools-scm). fallback_version keeps
|
|
40
|
+
# non-release jobs building on the shallow CI checkout, which has no tags.
|
|
41
|
+
[tool.setuptools_scm]
|
|
42
|
+
fallback_version = "0.0.0"
|
|
43
|
+
|
|
44
|
+
# Development toolchain (uv-native, PEP 735). CI installs it with
|
|
45
|
+
# `uv sync --group dev`. Not shipped to consumers — runtime deps live in
|
|
46
|
+
# [project.dependencies].
|
|
47
|
+
[dependency-groups]
|
|
48
|
+
dev = [
|
|
49
|
+
"ruff",
|
|
50
|
+
"mypy",
|
|
51
|
+
"pytest",
|
|
52
|
+
"pytest-cov",
|
|
53
|
+
"pytest-sugar",
|
|
54
|
+
"pytest-mock",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.setuptools.package-data]
|
|
58
|
+
"ichec_cicd" = ["py.typed"]
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["src"]
|
|
62
|
+
|
|
63
|
+
# --- ruff: format + lint (supersedes black, isort, flake8, pylint) ---
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
line-length = 88
|
|
66
|
+
target-version = "py314"
|
|
67
|
+
src = ["src", "tests"]
|
|
68
|
+
|
|
69
|
+
[tool.ruff.lint]
|
|
70
|
+
# E/W pycodestyle, F pyflakes, I import-sort (was isort), N pep8-naming,
|
|
71
|
+
# UP pyupgrade, B bugbear. Extend deliberately, not by pulling in "ALL".
|
|
72
|
+
select = ["E", "W", "F", "I", "N", "UP", "B"]
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint.isort]
|
|
75
|
+
known-first-party = ["ichec_cicd"]
|
|
76
|
+
|
|
77
|
+
[tool.mypy]
|
|
78
|
+
ignore_missing_imports = true
|
|
79
|
+
|
|
80
|
+
[tool.pytest.ini_options]
|
|
81
|
+
testpaths = ["tests",]
|
|
82
|
+
log_cli = 1
|
|
83
|
+
log_cli_level = "debug"
|
|
84
|
+
addopts = "--cov=ichec_cicd --cov-report term --cov-fail-under=18 --cov-report xml:coverage.xml --cov-report html"
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .ci import * # NOQA
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from ichec_platform_core import filesystem as fs
|
|
7
|
+
from ichec_platform_core.system import process
|
|
8
|
+
from ichec_platform_core.version_control import (
|
|
9
|
+
GitlabClient,
|
|
10
|
+
GitlabInstance,
|
|
11
|
+
GitlabToken,
|
|
12
|
+
GitRepo,
|
|
13
|
+
GitUser,
|
|
14
|
+
)
|
|
15
|
+
from ichec_platform_core.version_control.gitlab_client import get_latest_release
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def gitlab_ci_push(
|
|
21
|
+
user_name: str,
|
|
22
|
+
user_email: str,
|
|
23
|
+
repo_url: str,
|
|
24
|
+
token: str,
|
|
25
|
+
message: str,
|
|
26
|
+
repo_dir: Path | None = None,
|
|
27
|
+
):
|
|
28
|
+
if repo_dir is None:
|
|
29
|
+
repo_dir = Path.cwd()
|
|
30
|
+
|
|
31
|
+
user = GitUser(name=user_name, email=user_email)
|
|
32
|
+
repo = GitRepo(user=user, path=repo_dir)
|
|
33
|
+
|
|
34
|
+
gitlab = GitlabClient(
|
|
35
|
+
instance=GitlabInstance(url=repo_url),
|
|
36
|
+
token=GitlabToken(value=token),
|
|
37
|
+
user=user,
|
|
38
|
+
local_repo=repo,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
remote_name = "origin"
|
|
42
|
+
if token:
|
|
43
|
+
remote_name = "oath_origin"
|
|
44
|
+
gitlab.push_change(message, remote_name=remote_name)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def sync_external_archive(
|
|
48
|
+
repo_dir: Path,
|
|
49
|
+
project_id: int,
|
|
50
|
+
asset_name: str,
|
|
51
|
+
archive_name: str,
|
|
52
|
+
sync_script: Path,
|
|
53
|
+
source_token: str = "",
|
|
54
|
+
user_name: str = "",
|
|
55
|
+
user_email: str = "",
|
|
56
|
+
url: str = "",
|
|
57
|
+
target_token: str = "",
|
|
58
|
+
target_repo_url: str = "",
|
|
59
|
+
):
|
|
60
|
+
|
|
61
|
+
# Download package
|
|
62
|
+
logger.info("Fetching remote asset from %s for project %s", url, project_id)
|
|
63
|
+
work_dir = repo_dir / "_temp"
|
|
64
|
+
os.makedirs(work_dir)
|
|
65
|
+
get_latest_release(
|
|
66
|
+
project_id, url, source_token, work_dir, asset_name, "PRIVATE-TOKEN"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logger.info("Extracting archive from %s", work_dir / asset_name)
|
|
70
|
+
fs.unpack_archive(work_dir / asset_name, work_dir)
|
|
71
|
+
(work_dir / asset_name).unlink()
|
|
72
|
+
|
|
73
|
+
# Run sync script
|
|
74
|
+
logger.info("Running sync with %s", repo_dir / sync_script)
|
|
75
|
+
process.run(f"{repo_dir / sync_script} {work_dir}")
|
|
76
|
+
|
|
77
|
+
# Clean work working directory
|
|
78
|
+
shutil.rmtree(work_dir)
|
|
79
|
+
|
|
80
|
+
# Commit and push change
|
|
81
|
+
logger.info("Pushing change")
|
|
82
|
+
gitlab_ci_push(
|
|
83
|
+
user_name,
|
|
84
|
+
user_email,
|
|
85
|
+
target_repo_url,
|
|
86
|
+
target_token,
|
|
87
|
+
"External_repo_sync",
|
|
88
|
+
repo_dir,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
logger.info("Finished external package sync")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from .ci import gitlab_ci_push, sync_external_archive
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def gitlab_ci_push_cli(args):
|
|
11
|
+
|
|
12
|
+
logger.info("CI pushing state of current checkout")
|
|
13
|
+
|
|
14
|
+
gitlab_ci_push(
|
|
15
|
+
args.user_name, args.user_email, args.repo_url, args.token, args.message
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
logger.info("CI finished pushing state of current checkout")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def register_ci_push(subparsers):
|
|
22
|
+
|
|
23
|
+
parser = subparsers.add_parser("ci_push")
|
|
24
|
+
parser.add_argument("--user_name", type=str, help="Name of the CI user")
|
|
25
|
+
parser.add_argument("--user_email", type=str, help="Email of the CI user")
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--instance_url", type=str, help="Url for the target ci instance"
|
|
28
|
+
)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--url", type=str, help="Url for the repo relative to the ci instance"
|
|
31
|
+
)
|
|
32
|
+
parser.add_argument("--token", type=str, help="Oath access token for the repo")
|
|
33
|
+
parser.add_argument("--message", type=str, help="Commit message")
|
|
34
|
+
parser.set_defaults(func=gitlab_ci_push_cli)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def sync_external_archive_cli(args):
|
|
38
|
+
|
|
39
|
+
logger.info("Starting external package sync")
|
|
40
|
+
|
|
41
|
+
sync_external_archive(
|
|
42
|
+
repo_dir=args.repo_dir,
|
|
43
|
+
project_id=args.project_id,
|
|
44
|
+
sync_script=args.sync_script,
|
|
45
|
+
asset_name=args.asset_name,
|
|
46
|
+
archive_name=args.archive_name,
|
|
47
|
+
source_token=args.source_token,
|
|
48
|
+
user_name=args.user_name,
|
|
49
|
+
user_email=args.user_email,
|
|
50
|
+
url=args.url,
|
|
51
|
+
target_token=args.target_token,
|
|
52
|
+
target_repo_url=args.target_repo_url,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
logger.info("Finished external package sync")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def register_sync_exterinal(subparsers):
|
|
59
|
+
|
|
60
|
+
parser = subparsers.add_parser("sync_external_archive")
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--repo_dir",
|
|
63
|
+
type=Path,
|
|
64
|
+
default=Path(os.getcwd()),
|
|
65
|
+
help="Path to the repo to increment the tag",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--project_id",
|
|
70
|
+
type=int,
|
|
71
|
+
help="The id of the project to sync against.",
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"--source_token", type=str, default="", help="Access token for the source repo"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
parser.add_argument("--user_name", type=str, default="", help="Name of the CI user")
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--user_email", type=str, default="", help="Email of the CI user"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
parser.add_argument(
|
|
83
|
+
"--url",
|
|
84
|
+
type=str,
|
|
85
|
+
default="https://git.ichec.ie",
|
|
86
|
+
help="Url for the Gitlab instance",
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--target_token", type=str, default="", help="Oath access token for the repo"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
parser.add_argument(
|
|
93
|
+
"--asset_name", type=str, help="Name of the release asset for the archive"
|
|
94
|
+
)
|
|
95
|
+
parser.add_argument(
|
|
96
|
+
"--archive_name", type=str, help="Name of the downloaded archive"
|
|
97
|
+
)
|
|
98
|
+
parser.add_argument(
|
|
99
|
+
"--sync_script", type=Path, help="Path to script to do the sync"
|
|
100
|
+
)
|
|
101
|
+
parser.add_argument(
|
|
102
|
+
"--target_repo_url", type=str, default="", help="Url for the target repo"
|
|
103
|
+
)
|
|
104
|
+
parser.set_defaults(func=sync_external_archive_cli)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def register(subparser):
|
|
108
|
+
|
|
109
|
+
register_ci_push(subparser)
|
|
110
|
+
register_sync_exterinal(subparser)
|
|
File without changes
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI handlers for the `container` module
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from ichec_platform_core.serialization import read_yaml
|
|
10
|
+
|
|
11
|
+
from ..manifest import ReleaseManifest
|
|
12
|
+
from .container import generate_containerfile
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def containerfile_generate_cli(args):
|
|
18
|
+
|
|
19
|
+
logger.info("Generating containerfile")
|
|
20
|
+
|
|
21
|
+
manifest = ReleaseManifest(**read_yaml(args.manifest))
|
|
22
|
+
|
|
23
|
+
generate_containerfile(
|
|
24
|
+
manifest, args.template_dir.resolve(), args.output_dir.resolve()
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger.info("Finished generating containerfile")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def register_containerfile_parser(subparsers):
|
|
31
|
+
|
|
32
|
+
parser = subparsers.add_parser("containerfile")
|
|
33
|
+
containerfile_subparsers = parser.add_subparsers(required=True)
|
|
34
|
+
|
|
35
|
+
generate_parser = containerfile_subparsers.add_parser("generate")
|
|
36
|
+
|
|
37
|
+
generate_parser.add_argument(
|
|
38
|
+
"--manifest",
|
|
39
|
+
type=Path,
|
|
40
|
+
help="Path to the repo's deployment manifest",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
generate_parser.add_argument(
|
|
44
|
+
"--template_dir",
|
|
45
|
+
type=Path,
|
|
46
|
+
help="Directory with container templates",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
generate_parser.add_argument(
|
|
50
|
+
"--output_dir",
|
|
51
|
+
type=Path,
|
|
52
|
+
default=Path(os.getcwd()),
|
|
53
|
+
help="Directory to output generated files",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
generate_parser.set_defaults(func=containerfile_generate_cli)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def register(subparsers):
|
|
60
|
+
|
|
61
|
+
register_containerfile_parser(subparsers)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from ..manifest import ReleaseManifest
|
|
4
|
+
from ..packaging import generate_django_containerfile, generate_fastapi_containerfile
|
|
5
|
+
|
|
6
|
+
_GENERATORS = {
|
|
7
|
+
"django": generate_django_containerfile,
|
|
8
|
+
"fastapi": generate_fastapi_containerfile,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def generate_containerfile(
|
|
13
|
+
manifest: ReleaseManifest,
|
|
14
|
+
template_dir: Path,
|
|
15
|
+
output_dir: Path,
|
|
16
|
+
generators: dict | None = None,
|
|
17
|
+
):
|
|
18
|
+
|
|
19
|
+
if not generators:
|
|
20
|
+
generators = _GENERATORS
|
|
21
|
+
|
|
22
|
+
if manifest.project.type not in generators:
|
|
23
|
+
raise RuntimeError(
|
|
24
|
+
f"Generator not found for supplied project type: {manifest.project.type}"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
generators[manifest.project.type](template_dir, manifest, output_dir)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
This is the entrypoint for the `iccicd` application.
|
|
5
|
+
|
|
6
|
+
CLI arguments and handlers for individual modules are
|
|
7
|
+
registered here and defined in the respective `cli` submodules.
|
|
8
|
+
|
|
9
|
+
`launch_common()` is common code run before all handlers.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import argparse
|
|
13
|
+
import logging
|
|
14
|
+
|
|
15
|
+
from ichec_platform_core import logging_utils, runtime
|
|
16
|
+
|
|
17
|
+
import ichec_cicd.ci.cli
|
|
18
|
+
import ichec_cicd.container.cli
|
|
19
|
+
import ichec_cicd.packaging.cli
|
|
20
|
+
import ichec_cicd.repo.cli
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def launch_common(args) -> None:
|
|
26
|
+
"""
|
|
27
|
+
Run this code before all CLI handlers. It sets up a global
|
|
28
|
+
runtime context to store runtime configuration, such as the
|
|
29
|
+
'dry run' flag and sets up logging.
|
|
30
|
+
"""
|
|
31
|
+
runtime.ctx.set_is_dry_run(args.dry_run)
|
|
32
|
+
logging_utils.setup_default_logger()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main_cli():
|
|
36
|
+
"""
|
|
37
|
+
This method is associated with the `ichec_cicd` application in the
|
|
38
|
+
project's pyproject.toml, i.e. it will be run when `ichec_cicd` is
|
|
39
|
+
called in a terminal.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
parser = argparse.ArgumentParser()
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--dry_run",
|
|
45
|
+
type=int,
|
|
46
|
+
default=0,
|
|
47
|
+
help="Dry run script - 0 can modify, 1 can read, 2 no modify - no read",
|
|
48
|
+
)
|
|
49
|
+
subparsers = parser.add_subparsers(required=True)
|
|
50
|
+
|
|
51
|
+
ichec_cicd.packaging.cli.register(subparsers)
|
|
52
|
+
ichec_cicd.repo.cli.register(subparsers)
|
|
53
|
+
ichec_cicd.ci.cli.register(subparsers)
|
|
54
|
+
ichec_cicd.container.cli.register(subparsers)
|
|
55
|
+
|
|
56
|
+
args = parser.parse_args()
|
|
57
|
+
launch_common(args)
|
|
58
|
+
args.func(args)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
main_cli()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .manifest import * # NOQA
|