Browse Source
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>pull/423/head
9 changed files with 656 additions and 89 deletions
@ -0,0 +1,57 @@
|
||||
name: Release Sandbox |
||||
|
||||
permissions: |
||||
contents: read |
||||
|
||||
on: |
||||
workflow_dispatch: |
||||
inputs: |
||||
app: |
||||
description: The changed app |
||||
type: string |
||||
default: pyTermTk |
||||
version: |
||||
description: The app version |
||||
type: string |
||||
default: v0.0.0 |
||||
discord-message: |
||||
description: The release message |
||||
type: string |
||||
default: pyTermTk released |
||||
workflow_call: |
||||
inputs: |
||||
app: |
||||
description: The changed app |
||||
type: string |
||||
default: pyTermTk |
||||
version: |
||||
description: The app version |
||||
type: string |
||||
default: v0.0.0 |
||||
discord-message: |
||||
description: The release message |
||||
type: string |
||||
default: pyTermTk released |
||||
|
||||
jobs: |
||||
notify-discord: |
||||
# runs-on: ubuntu-latest |
||||
runs-on: self-hosted |
||||
steps: |
||||
- uses: actions/checkout@v4 |
||||
with: |
||||
ref: ${{ github.sha }} |
||||
- uses: actions/setup-python@v5 |
||||
with: |
||||
python-version: "3.x" |
||||
- name: Instrall deps |
||||
run: | |
||||
python -m pip install discord.py |
||||
- name: Deploy Discord message |
||||
env: |
||||
MESSAGE: ${{ inputs.discord-message }} |
||||
run: | |
||||
python tools/ci/social/notify_discord.py ${{ inputs.app }} ${{ inputs.version }} |
||||
|
||||
|
||||
|
||||
@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env python3 |
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import re |
||||
import sys |
||||
import glob |
||||
import json |
||||
import argparse |
||||
import fileinput |
||||
from dataclasses import dataclass |
||||
from enum import Enum |
||||
|
||||
from typing import List, Dict, Union |
||||
|
||||
class MatrixType(Enum): |
||||
ALL = "all" |
||||
PYPI = "pypi" |
||||
ITCH = "itch" |
||||
|
||||
@dataclass |
||||
class _AppData(): |
||||
name: str |
||||
path: str |
||||
version: str |
||||
pypi: bool = False |
||||
itch: bool = False |
||||
tag: str = "" |
||||
release_notes: str = "" |
||||
|
||||
def to_dict(self) -> Dict[str, Union[str,bool]]: |
||||
return { |
||||
"name" : self.name, |
||||
"path" : self.path, |
||||
"version" : self.version, |
||||
"pypi" : self.pypi, |
||||
"itch" : self.itch, |
||||
"tag" : self.tag, |
||||
"release-notes" : self.release_notes |
||||
} |
||||
|
||||
def _print_info(apps_data:List[_AppData]) -> None: |
||||
for _a in apps_data: |
||||
print(f"{_a.name} : {_a.version}") |
||||
|
||||
# for item in $(jq -r '.[].path' <<< ${APPS_ARRAY}) ; do; do |
||||
# # Update version in the project |
||||
# _VERSION=$(_get_version ${item}) |
||||
# _NAME=$(_get_name ${item}) |
||||
# if grep -q "${_NAME}: ${_VERSION}" <<< ' ${{ steps.release-please.outputs.pr }}' ; then |
||||
# sed -i \ |
||||
# "s|__version__:str.*|__version__:str = '${_VERSION}'|" \ |
||||
# ${item}/*/__init__.py |
||||
# sed "s|'pyTermTk *>=[^']*'|'pyTermTk>=${_VERSION_TTK}'|" -i ${item}/pyproject.toml |
||||
# echo ✅ Bumped ${_NAME} to ${_VERSION} |
||||
# else |
||||
# echo 🆗 No new release found for ${_NAME} |
||||
# fi |
||||
# done |
||||
def _upgrade_files(apps_data:List[_AppData], rp_data:Dict, dry_run:bool) -> None: |
||||
_ttk = [_a for _a in apps_data if _a.name=='pyTermTk'][0] |
||||
for _a in apps_data: |
||||
print(f"{_a.name} : {_a.version}") |
||||
if f"{_a.name}: {_a.version}" not in rp_data.get('pr',''): |
||||
print(f"🆗 No new release found for ${_a.name}") |
||||
else: |
||||
print(f"✅ Bumped ${_a.name} to ${_a.version}") |
||||
print(f"sed {_a.path}/*/__init__.py <<< {_a.version}") |
||||
|
||||
pattern = re.compile(r"__version__:str.*") |
||||
replacement=f"__version__:str = '{_a.version}'" |
||||
files = glob.glob(f"{_a.path}/*/__init__.py") |
||||
if dry_run: |
||||
print(files, replacement) |
||||
else: |
||||
for line in fileinput.input(files, inplace=True): |
||||
print(pattern.sub(replacement, line), end="") |
||||
|
||||
pattern = re.compile(r"'pyTermTk *>=[^']*'") |
||||
replacement = f"'pyTermTk>={_ttk.version}'" |
||||
|
||||
files = glob.glob(f"{_a.path}/pyproject.toml") |
||||
if dry_run: |
||||
print(files, replacement) |
||||
else: |
||||
for line in fileinput.input(files, inplace=True): |
||||
print(pattern.sub(replacement, line), end="") |
||||
|
||||
|
||||
def _gen_matrix(matrix_type: MatrixType, rp_data:Dict, apps_data:List[_AppData]) -> List[_AppData]: |
||||
if matrix_type == MatrixType.PYPI: |
||||
apps = [app for app in apps_data if app.pypi] |
||||
elif matrix_type == MatrixType.ITCH: |
||||
apps = [app for app in apps_data if app.itch] |
||||
elif matrix_type == MatrixType.ALL: |
||||
apps = apps_data |
||||
else: |
||||
raise ValueError(f"Invalid matrix type: {matrix_type}") |
||||
|
||||
# if 'pr' not in rp_data: |
||||
# return []# |
||||
|
||||
# pr = json.loads(rp_data['pr']) |
||||
|
||||
# print(rp_data) |
||||
# for app in apps: |
||||
# print(f"{app.name}: [{app.path}--release_created]: ", rp_data.get(f"{app.path}--release_created",False)) |
||||
|
||||
apps = [app for app in apps if rp_data.get(f"{app.path}--release_created",False) in ('true',True)] |
||||
for app in apps: |
||||
app.tag = rp_data.get(f"{app.path}--tag_name",'') |
||||
app.release_notes = rp_data.get(f"{app.path}--body",'') |
||||
|
||||
return apps |
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser(description="Release Helper Script") |
||||
# Configuration File Argument |
||||
parser.add_argument("--config", metavar="config_file", type=argparse.FileType("r"), help="Path to the configuration file") |
||||
parser.add_argument("--manifest", metavar="config_file", type=argparse.FileType("r"), help="Path to the configuration file") |
||||
|
||||
subparsers = parser.add_subparsers(title="Features", dest="feature") |
||||
|
||||
# Apps Feature |
||||
info_parser = subparsers.add_parser("info", help="Print release info") |
||||
|
||||
upgrade_parser = subparsers.add_parser("upgrade", help="update the app versions") |
||||
upgrade_parser.add_argument("--dry-run", action="store_true", help="Do not apply thw changes") |
||||
|
||||
# Apps Feature |
||||
apps_parser = subparsers.add_parser("apps", help="Apps related operations") |
||||
apps_parser.add_argument("--list", action="store_true", help="List available apps") |
||||
apps_parser.add_argument("--build", metavar="app_name", type=str, help="Build a specific app") |
||||
|
||||
# Matrix Feature |
||||
matrix_parser = subparsers.add_parser("matrix", help="Matrix related operations") |
||||
matrix_parser.add_argument("type", metavar="matrix_type", type=str, choices=[e.value for e in MatrixType], help="Specify the type of matrix to generate") |
||||
|
||||
args = parser.parse_args() |
||||
|
||||
# Load and parse configuration file if provided |
||||
config = {} |
||||
if args.config: |
||||
try: |
||||
config = json.load(args.config) # Parse the JSON file |
||||
# print(f"Loaded configuration: {json.dumps(config, indent=2)}") |
||||
except json.JSONDecodeError: |
||||
print(f"Error: Configuration file '{args.config.name}' is not valid JSON.") |
||||
sys.exit(1) |
||||
|
||||
# Load and parse configuration file if provided |
||||
manifest = {} |
||||
if args.manifest: |
||||
try: |
||||
manifest = json.load(args.manifest) # Parse the JSON file |
||||
# print(f"Loaded manifesturation: {json.dumps(manifest, indent=2)}") |
||||
except json.JSONDecodeError: |
||||
print(f"Error: Configuration file '{args.manifest.name}' is not valid JSON.") |
||||
sys.exit(1) |
||||
|
||||
input_data = {} |
||||
if not sys.stdin.isatty(): # or sys.stdin.peek(1): |
||||
try: |
||||
read = sys.stdin.read() |
||||
input_data = json.loads(read) |
||||
except json.JSONDecodeError: |
||||
print("Error: Invalid JSON input.") |
||||
sys.exit(1) |
||||
|
||||
apps_data = [ |
||||
_AppData( |
||||
name=_v.get('package-name',''), |
||||
path=_a, |
||||
version=manifest.get(_a,"0.0.0"), |
||||
itch=_v.get('itch',False), |
||||
pypi=_v.get('pypi',False)) |
||||
for _a,_v in config.get('packages',{}).items()] |
||||
|
||||
# print(apps_data) |
||||
|
||||
if args.feature == "info": |
||||
_print_info(apps_data) |
||||
elif args.feature == "upgrade": |
||||
print(args) |
||||
_upgrade_files(apps_data, input_data, args.dry_run) |
||||
elif args.feature == "apps": |
||||
if args.list: |
||||
print("Available Apps:") |
||||
for app in apps_data: |
||||
print(f" - {app.name}") |
||||
elif args.build: |
||||
print(f"Building app: {args.build}") |
||||
# Implement build logic here |
||||
else: |
||||
apps_parser.print_help() |
||||
elif args.feature == "matrix": |
||||
matrix_type = MatrixType(args.type) |
||||
matrix = _gen_matrix(matrix_type, input_data, apps_data) |
||||
# print(json.dumps( |
||||
# { |
||||
# 'has_matrix': bool(matrix), |
||||
# 'matrix':[app.to_dict() for app in matrix] |
||||
# } |
||||
# , indent=2)) |
||||
print(json.dumps([app.to_dict() for app in matrix], indent=2)) |
||||
else: |
||||
parser.print_help() |
||||
|
||||
if __name__ == "__main__": |
||||
main() |
||||
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3 |
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
|
||||
from .release_helper import * |
||||
|
||||
rp_pr_1 = '''{ |
||||
"releases_created": "false", |
||||
"paths_released": "[]", |
||||
"prs_created": "true", |
||||
"pr": "{\"headBranchName\":\"release-please--branches--main\",\"baseBranchName\":\"main\",\"number\":397,\"title\":\"chore: release main\",\"body\":\":robot: I have created a release *beep* *boop*\\n---\\n\\n\\n<details><summary>pyTermTk: 0.43.0-a.0</summary>\\n\\n## [0.43.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/pyTermTk-v0.42.1-a.0...pyTermTk-v0.43.0-a.0) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **kodeTab:** reworked iterWidget in iterItems\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Fixes\\n\\n* **spinbox:** better check for float, empty strings and negative numbers ([4909bf6](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/4909bf6756000f9450249b28f8c8379a2160415c))\\n\\n\\n### Chores\\n\\n* **kodeTab:** reworked iterWidget in iterItems ([47f73fc](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/47f73fc03a5a049ac3e6073dcadc09018b509328))\\n* **ttk:** workaround timer disconnect in case of error ([d70b2c1](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/d70b2c1c3cf25f7ffb479bc2850b3c9a3ca0fe0c))\\n\\n\\n### Refactors\\n\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n* **TTkColor:** improved typings ([711d611](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/711d611a73be0d0a6fce37e4624b5ae30847dd9c))\\n</details>\\n\\n<details><summary>ttkode: 0.4.0-a.2</summary>\\n\\n## [0.4.0-a.2](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/ttkode-v0.3.2-a.2...ttkode-v0.4.0-a.2) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Refactors\\n\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n</details>\\n\\n<details><summary>tlogg: 0.7.0-a.0</summary>\\n\\n## [0.7.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/tlogg-v0.6.0-a.0...tlogg-v0.7.0-a.0) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Refactors\\n\\n* move the main routine outside the a folder ([#400](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/400)) ([b1bb71f](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/b1bb71fd1ecd9c41a4cb016de15f1d695ea58ba5))\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n</details>\\n\\n---\\nThis PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).\",\"files\":[],\"labels\":[\"autorelease: pending\"]}", |
||||
"prs": "[{\"headBranchName\":\"release-please--branches--main\",\"baseBranchName\":\"main\",\"number\":397,\"title\":\"chore: release main\",\"body\":\":robot: I have created a release *beep* *boop*\\n---\\n\\n\\n<details><summary>pyTermTk: 0.43.0-a.0</summary>\\n\\n## [0.43.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/pyTermTk-v0.42.1-a.0...pyTermTk-v0.43.0-a.0) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **kodeTab:** reworked iterWidget in iterItems\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Fixes\\n\\n* **spinbox:** better check for float, empty strings and negative numbers ([4909bf6](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/4909bf6756000f9450249b28f8c8379a2160415c))\\n\\n\\n### Chores\\n\\n* **kodeTab:** reworked iterWidget in iterItems ([47f73fc](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/47f73fc03a5a049ac3e6073dcadc09018b509328))\\n* **ttk:** workaround timer disconnect in case of error ([d70b2c1](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/d70b2c1c3cf25f7ffb479bc2850b3c9a3ca0fe0c))\\n\\n\\n### Refactors\\n\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n* **TTkColor:** improved typings ([711d611](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/711d611a73be0d0a6fce37e4624b5ae30847dd9c))\\n</details>\\n\\n<details><summary>ttkode: 0.4.0-a.2</summary>\\n\\n## [0.4.0-a.2](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/ttkode-v0.3.2-a.2...ttkode-v0.4.0-a.2) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Refactors\\n\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n</details>\\n\\n<details><summary>tlogg: 0.7.0-a.0</summary>\\n\\n## [0.7.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/tlogg-v0.6.0-a.0...tlogg-v0.7.0-a.0) (2025-05-28)\\n\\n\\n### ⚠ BREAKING CHANGES\\n\\n* **TabWidget:** tab request close event need to be handled inside the app\\n\\n### Refactors\\n\\n* move the main routine outside the a folder ([#400](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/400)) ([b1bb71f](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/b1bb71fd1ecd9c41a4cb016de15f1d695ea58ba5))\\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\\n</details>\\n\\n---\\nThis PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).\",\"files\":[],\"labels\":[\"autorelease: pending\"]}]" |
||||
} |
||||
''' |
||||
|
||||
rp_release_1 = '''{ |
||||
"releases_created": "true", |
||||
"libs/pyTermTk--release_created": "true", |
||||
"libs/pyTermTk--id": "222844982", |
||||
"libs/pyTermTk--name": "pyTermTk: v0.43.0-a.0", |
||||
"libs/pyTermTk--tag_name": "pyTermTk-v0.43.0-a.0", |
||||
"libs/pyTermTk--sha": "edce717e527f2fe93a8a0c7f17e08a6b5fecd7bd", |
||||
"libs/pyTermTk--body": "## [0.43.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/pyTermTk-v0.42.1-a.0...pyTermTk-v0.43.0-a.0) (2025-06-03)\n\n\n### ⚠ BREAKING CHANGES\n\n* **kodeTab:** reworked iterWidget in iterItems\n* **TabWidget:** tab request close event need to be handled inside the app\n\n### Fixes\n\n* **spinbox:** better check for float, empty strings and negative numbers ([4909bf6](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/4909bf6756000f9450249b28f8c8379a2160415c))\n\n\n### Chores\n\n* autogen code for scrollarea classes ([#406](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/406)) ([fef1b0e](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/fef1b0ea5bd6ddc8f3e8f93a23ea156071e77493))\n* **Input:** add support for ctrl and other key comination ([#404](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/404)) ([5c2bb92](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/5c2bb9202cd819aa573e9f0d9ea966a4d0e5c485))\n* **kodeTab:** reworked iterWidget in iterItems ([47f73fc](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/47f73fc03a5a049ac3e6073dcadc09018b509328))\n* **spinbox:** fix return type ([ddc53a0](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/ddc53a07653a6f3aa958509d7d400cc6c6264d91))\n* **spinbox:** handle left/right wheel event ([ce961a6](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/ce961a657573ee520b73fca7d4ae721a8837a1d0))\n* **ttk:** workaround timer disconnect in case of error ([d70b2c1](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/d70b2c1c3cf25f7ffb479bc2850b3c9a3ca0fe0c))\n\n\n### Refactors\n\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))\n* **TTkColor:** improved typings ([711d611](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/711d611a73be0d0a6fce37e4624b5ae30847dd9c))", |
||||
"libs/pyTermTk--html_url": "https://github.com/ceccopierangiolieugenio/pyTermTk/releases/tag/pyTermTk-v0.43.0-a.0", |
||||
"libs/pyTermTk--draft": "false", |
||||
"libs/pyTermTk--upload_url": "https://uploads.github.com/repos/ceccopierangiolieugenio/pyTermTk/releases/222844982/assets{?name,label}", |
||||
"libs/pyTermTk--path": "libs/pyTermTk", |
||||
"libs/pyTermTk--version": "0.43.0-a.0", |
||||
"libs/pyTermTk--major": "0", |
||||
"libs/pyTermTk--minor": "43", |
||||
"libs/pyTermTk--patch": "0", |
||||
"libs/pyTermTk--prNumber": "397", |
||||
"apps/ttkode--release_created": "true", |
||||
"apps/ttkode--id": "222844984", |
||||
"apps/ttkode--name": "ttkode: v0.4.0-a.2", |
||||
"apps/ttkode--tag_name": "ttkode-v0.4.0-a.2", |
||||
"apps/ttkode--sha": "edce717e527f2fe93a8a0c7f17e08a6b5fecd7bd", |
||||
"apps/ttkode--body": "## [0.4.0-a.2](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/ttkode-v0.3.2-a.2...ttkode-v0.4.0-a.2) (2025-06-03)\n\n\n### ⚠ BREAKING CHANGES\n\n* **TabWidget:** tab request close event need to be handled inside the app\n\n### Features\n\n* add save feature ([#407](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/407)) ([26ff9b2](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/26ff9b2f0a81bddadeb6849d5d560ae67406f973))\n\n\n### Refactors\n\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))", |
||||
"apps/ttkode--html_url": "https://github.com/ceccopierangiolieugenio/pyTermTk/releases/tag/ttkode-v0.4.0-a.2", |
||||
"apps/ttkode--draft": "false", |
||||
"apps/ttkode--upload_url": "https://uploads.github.com/repos/ceccopierangiolieugenio/pyTermTk/releases/222844984/assets{?name,label}", |
||||
"apps/ttkode--path": "apps/ttkode", |
||||
"apps/ttkode--version": "0.4.0-a.2", |
||||
"apps/ttkode--major": "0", |
||||
"apps/ttkode--minor": "4", |
||||
"apps/ttkode--patch": "0", |
||||
"apps/ttkode--prNumber": "397", |
||||
"apps/tlogg--release_created": "true", |
||||
"apps/tlogg--id": "222844986", |
||||
"apps/tlogg--name": "tlogg: v0.7.0-a.0", |
||||
"apps/tlogg--tag_name": "tlogg-v0.7.0-a.0", |
||||
"apps/tlogg--sha": "edce717e527f2fe93a8a0c7f17e08a6b5fecd7bd", |
||||
"apps/tlogg--body": "## [0.7.0-a.0](https://github.com/ceccopierangiolieugenio/pyTermTk/compare/tlogg-v0.6.0-a.0...tlogg-v0.7.0-a.0) (2025-06-03)\n\n\n### ⚠ BREAKING CHANGES\n\n* **TabWidget:** tab request close event need to be handled inside the app\n\n### Refactors\n\n* move the main routine outside the a folder ([#400](https://github.com/ceccopierangiolieugenio/pyTermTk/issues/400)) ([b1bb71f](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/b1bb71fd1ecd9c41a4cb016de15f1d695ea58ba5))\n* **TabWidget:** tab request close event need to be handled inside the app ([9420adf](https://github.com/ceccopierangiolieugenio/pyTermTk/commit/9420adf68e2184482cd71266f280c560ea911f45))", |
||||
"apps/tlogg--html_url": "https://github.com/ceccopierangiolieugenio/pyTermTk/releases/tag/tlogg-v0.7.0-a.0", |
||||
"apps/tlogg--draft": "false", |
||||
"apps/tlogg--upload_url": "https://uploads.github.com/repos/ceccopierangiolieugenio/pyTermTk/releases/222844986/assets{?name,label}", |
||||
"apps/tlogg--path": "apps/tlogg", |
||||
"apps/tlogg--version": "0.7.0-a.0", |
||||
"apps/tlogg--major": "0", |
||||
"apps/tlogg--minor": "7", |
||||
"apps/tlogg--patch": "0", |
||||
"apps/tlogg--prNumber": "397", |
||||
"paths_released": "[\"libs/pyTermTk\",\"apps/ttkode\",\"apps/tlogg\"]", |
||||
"prs_created": "false" |
||||
}''' |
||||
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3 |
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE. |
||||
|
||||
import os, sys |
||||
import re |
||||
import asyncio |
||||
import argparse |
||||
from typing import Dict,List,Any |
||||
|
||||
import discord |
||||
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__)) |
||||
sys.path.append(current_dir) |
||||
from ci_tools.social.social_common import get_social_data, SocialData, get_env_var |
||||
|
||||
async def send_discord_message(version: str, data:SocialData): |
||||
token = get_env_var("DISCORD_TOKEN") |
||||
message = get_env_var("MESSAGE") |
||||
|
||||
intents = discord.Intents.default() |
||||
client = discord.Client(intents=intents) |
||||
|
||||
embed = discord.Embed( |
||||
title=f"{data.name} Released!!!", |
||||
url=data.link, |
||||
# description="Here's a new feature we added.", |
||||
color=0x00ff00, |
||||
) |
||||
embed.add_field(name="Version", value=version, inline=True) |
||||
# embed.add_field(name="What's New:", value=message, inline=False) |
||||
|
||||
# embed.set_image(url="https://example.com/image.png") |
||||
# embed.add_field(name="Feature", value="Auto-messaging", inline=False) |
||||
embed.set_footer(text="Bot by Pier...") |
||||
message = re.sub(r'\((https?://[^\)]+)\)', r'(<\1>)', message).replace('\\n','\n')[:2000] |
||||
# print(message) |
||||
# exit(1) |
||||
|
||||
@client.event |
||||
async def on_ready(): |
||||
print(f'Logged in as {client.user}') |
||||
channel = client.get_channel(data.discord_channel_id) |
||||
await channel.send(embed=embed) |
||||
await channel.send(message) |
||||
await client.close() # Optional: close after sending |
||||
|
||||
await client.start(token) |
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser(description="Send a Discord notification.") |
||||
parser.add_argument("app", type=str, help="The application name.") |
||||
parser.add_argument("version", type=str, help="The application version.") |
||||
args = parser.parse_args() |
||||
|
||||
data = get_social_data(args.app) |
||||
if not data: |
||||
raise ValueError(f"app: {args.app} is not recognised") |
||||
|
||||
asyncio.run(send_discord_message(args.version, data)) |
||||
|
||||
if __name__ == "__main__": |
||||
main() |
||||
@ -0,0 +1,68 @@
|
||||
# MIT License |
||||
# |
||||
# Copyright (c) 2025 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
||||
# |
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
# of this software and associated documentation files (the "Software"), to deal |
||||
# in the Software without restriction, including without limitation the rights |
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
# copies of the Software, and to permit persons to whom the Software is |
||||
# furnished to do so, subject to the following conditions: |
||||
# |
||||
# The above copyright notice and this permission notice shall be included in all |
||||
# copies or substantial portions of the Software. |
||||
# |
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
# SOFTWARE.from dataclasses import dataclass |
||||
|
||||
__all__ = ['get_social_data','SocialData','get_env_var'] |
||||
|
||||
import os |
||||
from dataclasses import dataclass |
||||
from typing import List |
||||
|
||||
@dataclass |
||||
class SocialData(): |
||||
name: str |
||||
link: str |
||||
discord_channel_id: int |
||||
|
||||
_all_data:List[SocialData] = [ |
||||
SocialData( |
||||
name='pytermtk', |
||||
link='https://github.com/ceccopierangiolieugenio/pyTermTk', |
||||
discord_channel_id=1379381341145268305, |
||||
), |
||||
SocialData( |
||||
name='ttkode', |
||||
link='https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/apps/ttkode', |
||||
discord_channel_id=1379381474783924295, |
||||
), |
||||
SocialData( |
||||
name='dumbpainttool', |
||||
link='https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/apps/dumbPaintTool', |
||||
discord_channel_id=1379381571412430931, |
||||
), |
||||
SocialData( |
||||
name='tlogg', |
||||
link='https://github.com/ceccopierangiolieugenio/pyTermTk/tree/main/apps/tlogg', |
||||
discord_channel_id=1379381593378000916, |
||||
), |
||||
] |
||||
|
||||
def get_social_data(app:str) -> SocialData: |
||||
for _sd in _all_data: |
||||
if _sd.name.lower() == app.lower(): |
||||
return _sd |
||||
raise ValueError(f"app: {app} is not recognised") |
||||
|
||||
def get_env_var(name:str) -> str: |
||||
value = os.environ.get(name) |
||||
if value is None: |
||||
raise EnvironmentError(f"{name} environment variable is not available") |
||||
return value |
||||
@ -0,0 +1,27 @@
|
||||
[build-system] |
||||
requires = ["setuptools>=45", "wheel"] |
||||
build-backend = "setuptools.build_meta" |
||||
|
||||
[project] |
||||
name = "ci_tools" |
||||
version = "0.1.0" |
||||
description = "ci helpers" |
||||
authors = [ |
||||
{name = "Eugenio Parodi", email = "ceccopierangiolieugenio@googlemail.com"}, |
||||
] |
||||
requires-python = ">=3.9" |
||||
dependencies = [ |
||||
'GitPython==3.1.44' |
||||
] |
||||
|
||||
[project.optional-dependencies] |
||||
social = [ |
||||
'discord.py==2.5.2' |
||||
] |
||||
|
||||
[project.scripts] |
||||
release-helper = "ci_tools.release_helper:main" |
||||
notify-discord = "ci_tools.social.notify_discord:main" |
||||
|
||||
[tool.setuptools] |
||||
packages = ["ci_tools"] |
||||
Loading…
Reference in new issue