tag-publish 0.0.0__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.
- tag_publish-0.0.0/LICENSE +22 -0
- tag_publish-0.0.0/PKG-INFO +394 -0
- tag_publish-0.0.0/README.md +357 -0
- tag_publish-0.0.0/pyproject.toml +105 -0
- tag_publish-0.0.0/tag_publish/__init__.py +235 -0
- tag_publish-0.0.0/tag_publish/cli.py +527 -0
- tag_publish-0.0.0/tag_publish/configuration.py +629 -0
- tag_publish-0.0.0/tag_publish/lib/__init__.py +0 -0
- tag_publish-0.0.0/tag_publish/lib/docker.py +138 -0
- tag_publish-0.0.0/tag_publish/lib/oidc.py +188 -0
- tag_publish-0.0.0/tag_publish/new.py +277 -0
- tag_publish-0.0.0/tag_publish/publish.py +380 -0
- tag_publish-0.0.0/tag_publish/py.typed +0 -0
- tag_publish-0.0.0/tag_publish/schema.json +356 -0
- tag_publish-0.0.0/tag_publish/versions.yaml +3 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2020-2026, Camptocamp SA
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
list of conditions and the following disclaimer.
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
|
11
|
+
and/or other materials provided with the distribution.
|
|
12
|
+
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
20
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tag-publish
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: Tools used to publish Python packages, Docker images and Helm charts for GitHub tag and branch
|
|
5
|
+
License: FreeBSD
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: ci
|
|
8
|
+
Author: Camptocamp
|
|
9
|
+
Author-email: info@camptocamp.com
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Dist: PyYAML (>=6,<7)
|
|
24
|
+
Requires-Dist: applications-download (>=1,<2)
|
|
25
|
+
Requires-Dist: debian-inspector (>=31,<32)
|
|
26
|
+
Requires-Dist: githubkit (>=0,<1)
|
|
27
|
+
Requires-Dist: id (>=1,<2)
|
|
28
|
+
Requires-Dist: jsonschema-validator-new (>=0,<1)
|
|
29
|
+
Requires-Dist: multi-repo-automation (>=1,<2)
|
|
30
|
+
Requires-Dist: requests (>=2,<3)
|
|
31
|
+
Requires-Dist: security-md (>=1,<2)
|
|
32
|
+
Requires-Dist: twine (>=6,<7)
|
|
33
|
+
Project-URL: Bug Tracker, https://github.com/camptocamp/tag-publish/issues
|
|
34
|
+
Project-URL: Repository, https://github.com/camptocamp/tag-publish
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Tag Publish
|
|
38
|
+
|
|
39
|
+
## Publishing
|
|
40
|
+
|
|
41
|
+
The main goals of Tag Publish offer the commands to publish the project,
|
|
42
|
+
Using a tag, a stabilization branch, a feature branch or a pull request.
|
|
43
|
+
|
|
44
|
+
When possible it can do a secret-less publishing (privileged in defaults), if it's not possible the login should be done before the publishing.
|
|
45
|
+
|
|
46
|
+
See the [documentation](https://github.com/camptocamp/c2cciutils/wiki/Publishing).
|
|
47
|
+
|
|
48
|
+
## Startup
|
|
49
|
+
|
|
50
|
+
Set the permissions:
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
permissions:
|
|
54
|
+
# To publish Docker images on GHCR, npm packages and Helm charts on OCI registry
|
|
55
|
+
packages: write
|
|
56
|
+
# To publish Python packages using OIDC and for cosign keyless signing
|
|
57
|
+
id-token: write
|
|
58
|
+
# To publish Helm charts (chart-releaser) and send repository dispatch notifications
|
|
59
|
+
contents: write
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Install the package in the worklow:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
- name: Install tag-publish
|
|
66
|
+
run: pip install tag-publish
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Do the publishing:
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
- name: Publish
|
|
73
|
+
run: tag-publish
|
|
74
|
+
env:
|
|
75
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## New version
|
|
79
|
+
|
|
80
|
+
To create a new version you should create a Git tag with the version number.
|
|
81
|
+
|
|
82
|
+
## New stabilization branch
|
|
83
|
+
|
|
84
|
+
To create a new minor version you just should run `tag-publish-new --version=<version>`.
|
|
85
|
+
|
|
86
|
+
This will create the stabilization branch and will create a new pull request to update
|
|
87
|
+
the `SECURITY.md` file and the Renovate configuration.
|
|
88
|
+
|
|
89
|
+
This will also create the tags for the backport.
|
|
90
|
+
|
|
91
|
+
You are welcome to run `tag-publish-new --help` to see what's it's done.
|
|
92
|
+
|
|
93
|
+
Note that it didn't create a tag, you should do it manually.
|
|
94
|
+
|
|
95
|
+
To create a patch version you should just create tag.
|
|
96
|
+
|
|
97
|
+
## Kind of publishing
|
|
98
|
+
|
|
99
|
+
This tool can publish on different kind of versions:
|
|
100
|
+
|
|
101
|
+
- `tag`: Related to a Git tag.
|
|
102
|
+
- `default_branch`: Related to the default branch.
|
|
103
|
+
- `stabilization_branch`: Related to a stabilization branch (including the default branch).
|
|
104
|
+
- `feature_branch`: Related to a feature branch or a pull request.
|
|
105
|
+
|
|
106
|
+
We can also publish on different kind of versions like `rebuild` by using the `--type` argument.
|
|
107
|
+
|
|
108
|
+
## SECURITY.md
|
|
109
|
+
|
|
110
|
+
The `SECURITY.md` file should contain the security policy of the repository, especially the end of
|
|
111
|
+
support dates.
|
|
112
|
+
|
|
113
|
+
For compatibility with [`security.md`](https://github.com/sbrunner/security.md/) it should contain an array
|
|
114
|
+
with at least the columns `Version` and `Supported Until`. The `Version` column will contain the concerned
|
|
115
|
+
version.
|
|
116
|
+
The `Supported Until` will contain the date of end of support `dd/mm/yyyy`.
|
|
117
|
+
It can also contain the following sentences:
|
|
118
|
+
|
|
119
|
+
- `Unsupported`: no longer supported => no audit, no rebuild.
|
|
120
|
+
- `Best effort`: the support is ended, it is still rebuilt and audited, but this can be stopped without any notice.
|
|
121
|
+
- `To be defined`: not yet released or the date will be set related of another project release date (like for GeoMapFish).
|
|
122
|
+
|
|
123
|
+
See also [GitHub Documentation](https://docs.github.com/en/github/managing-security-vulnerabilities/adding-a-security-policy-to-your-repository)
|
|
124
|
+
|
|
125
|
+
## Configuration
|
|
126
|
+
|
|
127
|
+
The configuration file is `.github/publish.yaml`, the schema is `https://raw.githubusercontent.com/camptocamp/tag-publish/<version>/tag_publish/schema.json`.
|
|
128
|
+
|
|
129
|
+
### Dry run
|
|
130
|
+
|
|
131
|
+
Dry run publish: `GITHUB_REF=... tag-publish --dry-run ...`
|
|
132
|
+
|
|
133
|
+
### Python package to pypi repository
|
|
134
|
+
|
|
135
|
+
Minimum configuration:
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
pypi:
|
|
139
|
+
packages:
|
|
140
|
+
- {}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
If the file `~/.pypirc` didn't exists we will do a login using OpenId Connect (OIDC), see:
|
|
144
|
+
https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-pypi.
|
|
145
|
+
|
|
146
|
+
By default the package will be published only on tag, if you want to publish on stabilization branch you should add
|
|
147
|
+
a `versions` key with the list of versions you want to publish, that can be:
|
|
148
|
+
`rebuild` (specified with --type), `tag`, `default_branch`, `stabilization_branch`, `feature_branch`, `pull_request` (for pull request merge: number)
|
|
149
|
+
|
|
150
|
+
It we have a `setup.py` file, we will be in legacy mode:
|
|
151
|
+
When publishing, the version computed from arguments or `GITHUB_REF` is put in environment variable `VERSION`, thus you should use it in `setup.py`, example:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
VERSION = os.environ.get("VERSION", "1.0.0")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Also we consider that we use `poetry` with [poetry-dynamic-versioning](https://pypi.org/project/poetry-dynamic-versioning/) to manage the version, and [poetry-plugin-tweak-dependencies-version](https://pypi.org/project/poetry-plugin-tweak-dependencies-version/) to manage the dependencies versions.
|
|
158
|
+
|
|
159
|
+
Example of configuration:
|
|
160
|
+
|
|
161
|
+
```toml
|
|
162
|
+
[tool.poetry-dynamic-versioning]
|
|
163
|
+
enable = true
|
|
164
|
+
vcs = "git"
|
|
165
|
+
pattern = "^(?P<base>\\d+(\\.\\d+)*)"
|
|
166
|
+
format-jinja = """
|
|
167
|
+
{%- if env.get("VERSION_TYPE") == "default_branch" -%}
|
|
168
|
+
{{serialize_pep440(bump_version(base, 1), dev=distance)}}
|
|
169
|
+
{%- elif env.get("VERSION_TYPE") == "stabilization_branch" -%}
|
|
170
|
+
{{serialize_pep440(bump_version(base, 2), dev=distance)}}
|
|
171
|
+
{%- elif distance == 0 -%}
|
|
172
|
+
{{serialize_pep440(base)}}
|
|
173
|
+
{%- else -%}
|
|
174
|
+
{{serialize_pep440(bump_version(base), dev=distance)}}
|
|
175
|
+
{%- endif -%}
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Note that we can access to the environment variables `VERSION`,`VERSION_TYPE`.
|
|
181
|
+
|
|
182
|
+
Then by default:
|
|
183
|
+
|
|
184
|
+
- Tag with `1.2.3` => release `1.2.3`
|
|
185
|
+
- Commit on feature branch just do a validation
|
|
186
|
+
- Commit on `master` branch after the tag 1.3.0 => release `1.4.0.dev1`
|
|
187
|
+
- Commit on `1.3` branch after the tag 1.3.0 => release `1.3.1.dev1`
|
|
188
|
+
|
|
189
|
+
#### Authentication
|
|
190
|
+
|
|
191
|
+
If the file `~/.pypirc` exists we consider that we ar already logged in also
|
|
192
|
+
we will do the login with the `pypi` server with OpenID Connect (OIDC).
|
|
193
|
+
|
|
194
|
+
The OIDC login is recommended because it didn't needs any additional secrets,
|
|
195
|
+
but it need some configuration on pypi in the package,
|
|
196
|
+
see the [GitHub Documentation](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-pypi#adding-the-identity-provider-to-pypi).
|
|
197
|
+
|
|
198
|
+
The required permissions is `id-token: write`.
|
|
199
|
+
|
|
200
|
+
#### Integration if the package directly in a Docker image
|
|
201
|
+
|
|
202
|
+
To make it working in the `Dockerfile` you should have in the `poetry` stage:
|
|
203
|
+
|
|
204
|
+
```Dockerfile
|
|
205
|
+
ENV POETRY_DYNAMIC_VERSIONING_BYPASS=dev
|
|
206
|
+
RUN poetry export --extras=checks --extras=publish --output=requirements.txt \
|
|
207
|
+
&& poetry export --with=dev --output=requirements-dev.txt
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
And in the `run` stage
|
|
211
|
+
|
|
212
|
+
```Dockerfile
|
|
213
|
+
ARG VERSION=dev
|
|
214
|
+
RUN --mount=type=cache,target=/root/.cache \
|
|
215
|
+
POETRY_DYNAMIC_VERSIONING_BYPASS=${VERSION} python3 -m pip install --disable-pip-version-check --no-deps --editable=.
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
And in the `Makefile`:
|
|
219
|
+
|
|
220
|
+
```Makefile
|
|
221
|
+
VERSION = $(strip $(shell poetry version --short))
|
|
222
|
+
|
|
223
|
+
.PHONY: build
|
|
224
|
+
build: ## Build the Docker images
|
|
225
|
+
docker build --build-arg=VERSION=$(VERSION) --tag=$(GITHUB_REPOSITORY) .
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Docker image to registry
|
|
229
|
+
|
|
230
|
+
The minimal config is like this:
|
|
231
|
+
|
|
232
|
+
```yaml
|
|
233
|
+
docker:
|
|
234
|
+
images:
|
|
235
|
+
- name: camptocamp/tag-publish
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
If you want to use the GitHub token to be logged in on ghcr you should set `auto_login` to `True`, the
|
|
239
|
+
requires the permissions are `packages: write`.
|
|
240
|
+
|
|
241
|
+
With that the image initially named `camptocamp/tag-publish:latest` will be published on GitHub GHCR and on Docker hub.
|
|
242
|
+
|
|
243
|
+
The full config is like this:
|
|
244
|
+
|
|
245
|
+
```yaml
|
|
246
|
+
docker:
|
|
247
|
+
github_oidc_login: True
|
|
248
|
+
latest: True
|
|
249
|
+
images:
|
|
250
|
+
- # The base name of the image we want to publish
|
|
251
|
+
name:
|
|
252
|
+
repository:
|
|
253
|
+
<internal_name>:
|
|
254
|
+
# The fqdn name of the server if not Docker hub
|
|
255
|
+
server:
|
|
256
|
+
# List of kinds of versions you want to publish, that can be: rebuild (specified using --type),
|
|
257
|
+
# tag, stabilization_branch, feature_branch, pull_request (for pull request merge: number)
|
|
258
|
+
version:
|
|
259
|
+
# List of tags we want to publish interpreted with `format(version=version)`
|
|
260
|
+
# e.g. if you use `{version}-lite` when you publish the version `1.2.3` the source tag
|
|
261
|
+
# (that should be built by the application build) is `latest-lite`, and it will be published
|
|
262
|
+
# with the tag `1.2.3-lite`.
|
|
263
|
+
tags:
|
|
264
|
+
# If your images are published by different jobs you can separate them in different groups
|
|
265
|
+
# and publish them with `tag-publish --group=<group>`
|
|
266
|
+
group:
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
By default, the last line of the `SECURITY.md` file will be published (`docker`) with the tag
|
|
270
|
+
`latest`. Set `latest` to `False` to disable it.
|
|
271
|
+
|
|
272
|
+
#### Use Renovate to trigger a new build instead of the legacy rebuild
|
|
273
|
+
|
|
274
|
+
If the `ci/dpkg-versions.yaml` or `.github/dpkg-versions.yaml` file is present, the package list will be updated on publishing.
|
|
275
|
+
|
|
276
|
+
The versions will be updated by [GHCI](https://github.com/camptocamp/github-app-geo-project/) application.
|
|
277
|
+
|
|
278
|
+
### Node package to npm repository
|
|
279
|
+
|
|
280
|
+
Minimum configuration:
|
|
281
|
+
|
|
282
|
+
```yaml
|
|
283
|
+
node:
|
|
284
|
+
packages:
|
|
285
|
+
- {}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
If the repository server is `npm.pkg.github.com` we will do a login using `GITHUB_TOKEN`.
|
|
289
|
+
|
|
290
|
+
To publish on `npm.pkg.github.com` you requires the permissions are `packages: write`, and the `id-token: write` for the provenance.
|
|
291
|
+
|
|
292
|
+
By default the package will be published only on tag.
|
|
293
|
+
|
|
294
|
+
### HELM
|
|
295
|
+
|
|
296
|
+
The minimal config is like this:
|
|
297
|
+
|
|
298
|
+
```yaml
|
|
299
|
+
helm:
|
|
300
|
+
packages:
|
|
301
|
+
- {}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
This will publish the `helm` charts in the current folder using [chart releaser](https://github.com/helm/chart-releaser).
|
|
305
|
+
|
|
306
|
+
The artifacts will be attached to a GitHub release, and the `index.yaml` file will be updated in the `gh-pages` branch.
|
|
307
|
+
|
|
308
|
+
The required permission is `contents: write`.
|
|
309
|
+
|
|
310
|
+
Create the required `gh-pages` branch:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
git checkout --orphan gh-pages
|
|
314
|
+
git reset --hard
|
|
315
|
+
git commit --allow-empty -m "Initialize gh-pages branch"
|
|
316
|
+
git push origin gh-pages
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
#### OCI registry publishing
|
|
320
|
+
|
|
321
|
+
By default, the Helm chart is also published to an OCI registry (`ghcr.io/<owner>/<repo>`) and signed with [cosign](https://github.com/sigstore/cosign) using keyless signing.
|
|
322
|
+
|
|
323
|
+
The chart is pushed to `ghcr.io/<owner>/<repo>:<version>` automatically.
|
|
324
|
+
|
|
325
|
+
The required permissions are `packages: write` (for pushing to ghcr.io) and `id-token: write` (for cosign keyless signing).
|
|
326
|
+
|
|
327
|
+
To customize the OCI publishing:
|
|
328
|
+
|
|
329
|
+
```yaml
|
|
330
|
+
helm:
|
|
331
|
+
packages:
|
|
332
|
+
- folder: charts/my-chart
|
|
333
|
+
oci:
|
|
334
|
+
enabled: true # default: true
|
|
335
|
+
registry: ghcr.io # default: ghcr.io
|
|
336
|
+
sign: true # default: true, keyless signing via cosign
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
To disable OCI publishing:
|
|
340
|
+
|
|
341
|
+
```yaml
|
|
342
|
+
helm:
|
|
343
|
+
packages:
|
|
344
|
+
- {}
|
|
345
|
+
oci:
|
|
346
|
+
enabled: false
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Dispatch
|
|
350
|
+
|
|
351
|
+
The minimal config is like this:
|
|
352
|
+
|
|
353
|
+
```yaml
|
|
354
|
+
dispatch:
|
|
355
|
+
- {}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
The required permission is `contents: write`.
|
|
359
|
+
|
|
360
|
+
This will create a repository dispatch of type `published` on own repository with the `content` e.g.:
|
|
361
|
+
|
|
362
|
+
```json
|
|
363
|
+
{
|
|
364
|
+
"version": "1.2.3",
|
|
365
|
+
"version_type": "tag",
|
|
366
|
+
"repository": "camptocamp/tag-publish",
|
|
367
|
+
"items": [
|
|
368
|
+
{
|
|
369
|
+
"type": "docker",
|
|
370
|
+
"image": "camptocamp/tag-publish",
|
|
371
|
+
"repository": "ghcr.io",
|
|
372
|
+
"tag": "1.2.3"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"type": "pypi",
|
|
376
|
+
"path": "."
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"type": "helm",
|
|
380
|
+
"path": "."
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Contributing
|
|
387
|
+
|
|
388
|
+
Install the pre-commit hooks:
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
pip install pre-commit
|
|
392
|
+
pre-commit install --allow-missing-config
|
|
393
|
+
```
|
|
394
|
+
|