Skip to content

Commit 4d12c70

Browse files
committed
Add support to create pre-releases with a generated changelog
Signed-off-by: Tobias Wolf <[email protected]> On-behalf-of: SAP <[email protected]>
1 parent e5e9c52 commit 4d12c70

File tree

8 files changed

+671
-278
lines changed

8 files changed

+671
-278
lines changed

.github/workflows/release.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: pre-release
2+
3+
on:
4+
push:
5+
tags: [ 'v*' ]
6+
7+
jobs:
8+
create-pre-release:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout commit
13+
uses: actions/checkout@v6
14+
- name: Get the Git tag name
15+
id: get-tag-name
16+
run: echo "tag-name=${GITHUB_REF/refs\/tags\/v/}" >> "$GITHUB_OUTPUT"
17+
- id: changelog
18+
name: Prepare changelog
19+
run: |
20+
cargo install git-changelog
21+
- name: Create Release
22+
uses: actions/create-release@v1
23+
env:
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
with:
26+
tag_name: v${{ steps.get-tag-name.outputs.tag-name }}
27+
release_name: v${{ steps.get-tag-name.outputs.tag-name }}
28+
body: |-
29+
"python-gardenlinux-lib" release v${{ steps.get-tag-name.outputs.tag-name }}
30+
prerelease: true

poetry.lock

Lines changed: 315 additions & 231 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ packages = [{ include = "gardenlinux", from = "src" }]
1010
[tool.poetry.dependencies]
1111
python = ">=3.13"
1212
apt-repo = "^0.5"
13-
boto3 = "^1.40.57"
13+
boto3 = "^1.41.5"
1414
click = "^8.2.1"
1515
cryptography = "^46.0.1"
1616
jsonschema = "^4.25.1"
1717
networkx = "^3.5"
1818
oras = "^0.2.38"
1919
pygit2 = "^1.19.0"
2020
pygments = "^2.19.2"
21+
PyGithub = "^2.8.1"
2122
PyYAML = "^6.0.2"
2223
gitpython = "^3.1.45"
2324

@@ -26,11 +27,11 @@ bandit = "^1.8.6"
2627
black = "^25.1.0"
2728
moto = "^5.1.12"
2829
python-dotenv = "^1.1.1"
29-
pytest = "^9.0.0"
30+
pytest = "^9.0.1"
3031
pytest-cov = "^7.0.0"
3132
isort = "^7.0.0"
3233
requests-mock = "^1.12.1"
33-
pyright = "^1.1.403"
34+
pyright = "^1.1.407"
3435

3536
[tool.poetry.group.docs.dependencies]
3637
sphinx-rtd-theme = "^3.0.2"

src/gardenlinux/github/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
GitHub module
5+
"""
6+
7+
from .client import Client
8+
9+
__all__ = ["Client"]

src/gardenlinux/github/client.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
GitHub client
5+
"""
6+
7+
from logging import Logger
8+
from os import environ
9+
from typing import Any, Optional
10+
11+
from github import Auth, Github
12+
13+
from ..logger import LoggerSetup
14+
15+
16+
class Client(object):
17+
"""
18+
GitHub client instance to provide methods for interaction with GitHub API.
19+
20+
:author: Garden Linux Maintainers
21+
:copyright: Copyright 2024 SAP SE
22+
:package: gardenlinux
23+
:subpackage: github
24+
:since: 1.0.0
25+
:license: https://www.apache.org/licenses/LICENSE-2.0
26+
Apache License, Version 2.0
27+
"""
28+
29+
def __init__(self, token: Optional[str] = None, logger: Optional[Logger] = None):
30+
"""
31+
Constructor __init__(Client)
32+
33+
:param token: GitHub access token
34+
:param logger: Logger instance
35+
36+
:since: 1.0.0
37+
"""
38+
39+
self._client = None
40+
self._token = token
41+
42+
if token is None:
43+
token = environ.get("GITHUB_TOKEN")
44+
45+
if token is None:
46+
raise ValueError("GITHUB_TOKEN environment variable not set")
47+
48+
if logger is None or not logger.hasHandlers():
49+
logger = LoggerSetup.get_logger("gardenlinux.github")
50+
51+
self._logger = logger
52+
53+
@property
54+
def instance(self) -> Github:
55+
if self._client is None:
56+
self._client = Github(auth=Auth.Token(self._token))
57+
58+
return self._client
59+
60+
def __getattr__(self, name: str) -> Any:
61+
"""
62+
python.org: Called when an attribute lookup has not found the attribute in
63+
the usual places (i.e. it is not an instance attribute nor is it found in the
64+
class tree for self).
65+
66+
:param name: Attribute name
67+
68+
:return: (mixed) Attribute
69+
:since: 0.8.0
70+
"""
71+
72+
self._logger.debug(f"gardenlinux.github.Client.{name} accessed")
73+
return getattr(self.instance, name)
Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,15 @@
1-
import json
21
import os
32
import sys
43

54
import requests
65

7-
from gardenlinux.constants import RELEASE_ID_FILE, REQUESTS_TIMEOUTS
8-
from gardenlinux.logger import LoggerSetup
6+
from ..constants import RELEASE_ID_FILE, REQUESTS_TIMEOUTS
7+
from ..logger import LoggerSetup
8+
from .release import Release
99

1010
LOGGER = LoggerSetup.get_logger("gardenlinux.github.release", "INFO")
1111

1212

13-
def create_github_release(owner, repo, tag, commitish, latest, body):
14-
token = os.environ.get("GITHUB_TOKEN")
15-
if not token:
16-
raise ValueError("GITHUB_TOKEN environment variable not set")
17-
18-
headers = {
19-
"Authorization": f"token {token}",
20-
"Accept": "application/vnd.github.v3+json",
21-
}
22-
23-
data = {
24-
"tag_name": tag,
25-
"target_commitish": commitish,
26-
"name": tag,
27-
"body": body,
28-
"draft": False,
29-
"prerelease": False,
30-
"make_latest": "true" if latest else "false",
31-
}
32-
33-
response = requests.post(
34-
f"https://api.github.com/repos/{owner}/{repo}/releases",
35-
headers=headers,
36-
data=json.dumps(data),
37-
timeout=REQUESTS_TIMEOUTS,
38-
)
39-
40-
if response.status_code == 201:
41-
LOGGER.info("Release created successfully")
42-
response_json = response.json()
43-
return response_json.get("id")
44-
else:
45-
LOGGER.error("Failed to create release")
46-
LOGGER.debug(response.json())
47-
response.raise_for_status()
48-
49-
5013
def write_to_release_id_file(release_id):
5114
try:
5215
with open(RELEASE_ID_FILE, "w") as file:
@@ -94,3 +57,6 @@ def upload_to_github_release_page(
9457
f"Upload failed with status code {response.status_code}: {response.text}"
9558
)
9659
response.raise_for_status()
60+
61+
62+
__all__ = ["Release", "write_to_release_id_file", "upload_to_github_release_page"]

src/gardenlinux/github/release/__main__.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from gardenlinux.logger import LoggerSetup
55

66
from .release import (
7-
create_github_release,
7+
Release,
88
upload_to_github_release_page,
99
write_to_release_id_file,
1010
)
@@ -43,9 +43,13 @@ def main():
4343
print("This release would be created:")
4444
print(body)
4545
else:
46-
release_id = create_github_release(
47-
args.owner, args.repo, args.tag, args.commit, args.latest, body
48-
)
46+
release = Release(args.repo, args.owner)
47+
release.tag = args.tag
48+
release.body = body
49+
release.commit_hash = args.commit
50+
release.is_latest = args.latest
51+
52+
release_id = release.create()
4953
write_to_release_id_file(f"{release_id}")
5054
LOGGER.info(f"Release created with ID: {release_id}")
5155
elif args.command == "upload":

0 commit comments

Comments
 (0)