1
0
mirror of https://github.com/MaxenceG2M/github-release-notifier.git synced 2025-12-08 13:53:24 +00:00

20 Commits
v1 ... poc/pixi

Author SHA1 Message Date
e5b0e19053 Makefile to download needed bin
Permit to download easily just and pixi binary without custom software
2023-12-30 01:20:43 +01:00
52c07aeb89 Just: retrieve mailpit as mail wrapper 2023-12-30 01:20:43 +01:00
00abaab982 Use pixi as env manager
https://github.com/prefix-dev/pixi
2023-12-30 01:20:20 +01:00
fb4ac8ea73 Justfile: improve release process & doc 2023-12-30 01:19:13 +01:00
f4edb03979 Improve HTML template + improve links
Reduce size (from ~15kB to ~4kB)
Reduce incompatibility for emails

Link to project on project name
2023-12-30 01:07:11 +01:00
68fd6e78d9 🔧 Use mailpit instead mailhog
Adjust ofelia crontime to avoid reach Github API limits
2023-12-30 00:39:31 +01:00
e57d9cf656 Improve justfile init phase 2023-11-25 23:53:52 +01:00
8dba474e23 Validate configuration + readable error
Change docker-compose version - use Just to handle version
2023-11-25 01:57:44 +01:00
07dccee235 Just
(cherry picked from commit 5d67747b3a31177010e32ce9cb6a668cd1b5737c)
2023-11-25 01:57:44 +01:00
fd7e6b73d1 Overload config with environment variables
Improves mail configuration management
2023-11-10 00:52:19 +01:00
0ee46a5d9e Fix Pylint problems 2023-11-10 00:51:32 +01:00
9709947c28 Apply pre-commit + keep black commit sha 2023-11-10 00:15:01 +01:00
89e88c8a1b Black formatting 2023-11-10 00:14:00 +01:00
148c647ac7 Install pre-commit 2023-11-10 00:13:24 +01:00
02fad7767c Cron with Ofelia
https://github.com/mcuadros/ofelia
2023-11-09 20:09:40 +01:00
74e6488044 Dockerfile & docker compose
Adapt configuration for tests purposes
Justfile to simplificate flow
2023-09-11 00:44:13 +02:00
f3380139ed Fix template too long line for mail 2023-09-07 01:19:07 +02:00
92953dbb5c Update pit db 2020-07-04 17:49:39 +02:00
11834803c8 Use script path to determine conf & template path [task 1, status:done] 2020-07-04 17:33:48 +02:00
bd5bf11661 Fix: don't send mail if no news [task 2, status:done] 2020-07-04 01:03:26 +02:00
17 changed files with 1072 additions and 110 deletions

2
.git-blame-ignore-revs Normal file
View File

@@ -0,0 +1,2 @@
# Black format commit
89e88c8a1b26e2c6ca242d0bba6cdba8da35c3ae

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# GitHub syntax highlighting
pixi.lock linguist-language=YAML

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# pixi environments
.pixi
mailpit
.bin

28
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,28 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-added-large-files
- id: check-merge-conflict
- repo: https://github.com/psf/black
rev: 23.11.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
name: isort
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
hooks:
- id: autoflake
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.11.0
hooks:
- id: pretty-format-yaml
args: [--autofix, --indent, '2', --offset, '2']

10
Dockerfile Normal file
View File

@@ -0,0 +1,10 @@
FROM python:3.10-alpine3.18
RUN pip install requests
WORKDIR /app
COPY notifier.py template.html /app/
# TODO Dev purporse
COPY conf.ini /app/conf.ini
ENTRYPOINT ["python3", "/app/notifier.py"]

62
Justfile Normal file
View File

@@ -0,0 +1,62 @@
# https://github.com/casey/just
python := "pixi run python"
last_commit_sha1 := `git rev-parse --short HEAD`
remote_image_name := "gitea.gdemontauzan.fr/maxenceg2m/github-release-notifier"
remote_build_image := remote_image_name + ":" + last_commit_sha1
# Run the script
run: init
{{ python }} notifier.py
# Init python env with pixi
init:
pixi install
# Remove virtual env (pixi)
hclean:
rm -fr .pixi
# Run docker compose then show logs
dup: dbuild
docker compose up -d
docker compose logs
# Build with docker compose
dbuild:
docker compose build
# Down docker compose then build
drebuild: ddown dbuild
# Down docker compose
ddown:
docker compose down
# Docker build without cache
dforce-build:
docker compose build --no-cache
# Push a working images on registry, tagged with commit-sha1
dpush: dbuild
docker tag github-release-notifier {{ remote_build_image }}
docker push {{ remote_build_image }}
echo "To push a tagged version, do 'just release <version>'"
# Use just a number! Without 'v'! Release a version - create a tagged images, push it and create git tag.
release version: dbuild
docker tag github-release-notifier {{ remote_image_name }}:{{ version }}
docker push {{ remote_image_name }}:{{ version }}
git tag -a v{{ version }} -m ""
git push --tags
# MAILPIT PART
mailpit_version := "v1.11.0"
mailpit_archi := "linux-amd64"
mailpit_output := "mailpit-" + mailpit_version + "-" + mailpit_archi + ".tar.gz"
# Retrive mailpit bin
get-mail-wrapper:
echo {{mailpit_output}}
curl -L https://github.com/axllent/mailpit/releases/download/{{mailpit_version}}/mailpit-{{mailpit_archi}}.tar.gz --output {{mailpit_output}}
tar xf {{mailpit_output}} mailpit

32
Makefile Normal file
View File

@@ -0,0 +1,32 @@
ARCH ?= x86_64-unknown-linux-musl
JUST_VERSION ?= 1.16.0
JUST_TGZ ?= just-$(JUST_VERSION)-$(ARCH).tar.gz
PIXI_VERSION ?= 0.10.0
PIXI_TGZ ?= pixi-$(PIXI_VERSION)-$(ARCH).tar.gz
all: just pixi
@echo "You can add .bin folder in your path to enjoy pixi and just:" 'export PATH=$$PATH:$$(pwd)/.bin'
PATH=$$PATH:$(pwd)/.bin just
just: .bin/just
.bin/just: init .bin/$(JUST_TGZ)
tar xf ./.bin/$(JUST_TGZ) -C ./.bin just
@echo "just downloaded. Run './.bin/just' command to exec"
.bin/$(JUST_TGZ):
curl -L https://github.com/casey/just/releases/download/$(JUST_VERSION)/just-$(JUST_VERSION)-$(ARCH).tar.gz -o ./.bin/$(JUST_TGZ)
pixi: .bin/pixi
.bin/pixi: init .bin/$(PIXI_TGZ)
tar xf ./.bin/$(PIXI_TGZ) -C ./.bin ./pixi
@echo "pixi downloaded. Run './.bin/pixi' command to exec"
.bin/$(PIXI_TGZ):
curl -L https://github.com/prefix-dev/pixi/releases/download/v$(PIXI_VERSION)/pixi-$(ARCH).tar.gz -o ./.bin/$(PIXI_TGZ)
init:
mkdir -p .bin

View File

@@ -37,6 +37,9 @@ I wrote this script really quickly, certainly faster than this README. So I alre
* The script sends mail even if no new projets or release has been detected
* The biggest, you have to edit script to specify absolute path...
* A lot of other little problems, like the code that's disgusting and so on.
For who's asking: yes, it's normal that I have put all code in one main function [like a blind gunner.](https://media.giphy.com/media/1yMexL5rkwYhuiVEmZ/giphy.gif). Really quickly I said!
But overall, the script works and sends mail!
Hey boy, what is the `pit.db` file?
@@ -45,4 +48,34 @@ Oh, just for fun, and because I love this project, I use [pit by michaeldv](http
It makes me think I should push my python version of this project on occasion when I will take the time to do...
How to build it?
----------------
This project use two very cool projets to handle env & build:
- [**just**](https://github.com/casey/just) as an alternative to [GNU Make](https://www.gnu.org/software/make/manual/make.html)
- [**pixi**](https://github.com/prefix-dev/pixi) to manage python & dependancies environnment without question
You can install these two software by your way, or use the Makefile to do it: `$ make`.
This command will download & untar `just` and `pixie` into a hidden `.bin` folder and launch just target to do the rest.
> Don't forget to set a valid SMTP host/port in `config.ini`. Otherwise, notifier execution will fail. See below if you want to get a wrapper
Just's targets permit to:
- just run the script
- build a docker image
- create a release
- etc.
Use `.bin/just --list` to list all available target.
### Use mailpit to wrap mails
If you don't want to really send and receive mail, e.g. to test... things! I recommand [**mailpit**](https://github.com/axllent/mailpit).
You can quickly get it with just: `.bin/just get-mail-wrapper`.
Then execute-it: `./mailpit`.
By default, SMTP port is `1025`, and HTTP port to access to interface is `8025`.

View File

@@ -1,7 +1,7 @@
[config]
github_api_url = https://api.github.com/repos/
smtp_port = 25
smtp_server = localhost
smtp_port = 1025
smtp_server = mailpit
sender_email = sender@host.eu
receiver_email = receiver@anotherhost.eu

24
docker-compose.yml Normal file
View File

@@ -0,0 +1,24 @@
version: '3'
services:
notifier:
build: .
image: github-release-notifier
container_name: github-release-notifier
volumes:
- ./conf.ini:/app/conf.ini
mailpit:
image: axllent/mailpit
ports:
- "8025:8025"
- "1025:1025"
ofelia:
image: mcuadros/ofelia:latest
depends_on:
- notifier
command: daemon --config=/opt/config.ini
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./ofelia.ini:/opt/config.ini

View File

@@ -1,103 +1,138 @@
from configparser import ConfigParser
import json
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import configparser
import datetime
import json
import os
import smtplib
import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import requests
SMTP_PORT = 0
SMTP_SERVER = 'null'
SENDER_EMAIL = 'a@b.c'
RECEIVER_EMAIL = 'd@e.f'
class EnvInjection(configparser.Interpolation):
"""
Derived interpolation to take env variable before file variable.
Permit to keep the ini file for local / traditionnal use
And use env variable to overload configuration in a Docker usage.
"""
def before_get(self, parser, section, option, value, defaults):
file_value = super().before_get(parser, section, option, value, defaults)
if section != parser.default_section:
return file_value
env_value = os.getenv(option.upper())
return env_value if env_value else file_value
def main():
global SMTP_PORT, SMTP_SERVER, SENDER_EMAIL, RECEIVER_EMAIL
parser = ConfigParser()
parser.read('conf.ini')
script_dir = os.path.dirname(__file__)
conf_file = os.path.join(script_dir, "conf.ini")
template_file = os.path.join(script_dir, "template.html")
SMTP_PORT = parser.get('config', 'smtp_port')
SMTP_SERVER = parser.get('config', 'smtp_server')
SENDER_EMAIL = parser.get('config', 'sender_email')
RECEIVER_EMAIL = parser.get('config', 'receiver_email')
parser = configparser.ConfigParser(
default_section="config", interpolation=EnvInjection()
)
parser.read(conf_file)
default_config = parser["config"]
try:
projects = json.loads(parser.get("projects", "projects"))
except json.decoder.JSONDecodeError as jse:
print("ERROR: config file is not correctly JSON formatted!", end="\n\t")
print(jse)
sys.exit(1)
projects = json.loads(parser.get('projects', 'projects'))
new_releases = []
new_projects = []
if not parser.has_section('release'):
parser.add_section('release')
if not parser.has_section("release"):
parser.add_section("release")
for project in projects:
last_release = get_last_release(project)
if not parser.has_option('release', project):
if not parser.has_option("release", project):
new_projects.append(last_release)
else:
last_config_tag = parser.get('release', project)
if last_config_tag != last_release['release_tag']:
last_release['preview_tag'] = last_config_tag
last_config_tag = parser.get("release", project)
if last_config_tag != last_release["release_tag"]:
last_release["previous_tag"] = last_config_tag
new_releases.append(last_release)
parser.set('release', project, last_release['release_tag'])
parser.set("release", project, last_release["release_tag"])
if not new_releases and not new_projects:
print("No new projets or new release detected. Bye!")
return
content = ""
for new_r in new_releases:
content += """
<li><a href="{}" target="_blank">{}</a>: new release <a href="{}" target="_blank">{}</a> available (old: {}).
(published {})</li>
""".format(
new_r['release_url'],
new_r['project_name'],
new_r['release_url'],
new_r['release_tag'],
new_r['preview_tag'],
convert_date(new_r['published_date']))
content += f"""
<li>{get_html_project_link(new_r)}
: new release
{get_html_release_link(new_r)}
available (old: {new_r["previous_tag"]}).
(published {convert_date(new_r["published_date"])})</li>"""
for new_p in new_projects:
content += """
<li><a href="{}" target="_blank">{}</a> was added to your configuration. Last release: <a href="{}" target="_blank">{}</a>
(published {})</li>""".format(
new_p['release_url'],
new_p['project_name'],
new_p['release_url'],
new_p['release_tag'],
convert_date(new_p['published_date']))
content += f"""
<li>{get_html_project_link(new_p)}
was added to your configuration.
Last release:
{get_html_release_link(new_p)}
(published {convert_date(new_p["published_date"])})</li>"""
# print(content)
with open('template.html', 'r') as f_template:
with open(template_file, "r", encoding="utf-8") as f_template:
template = f_template.read()
send_mail(template.replace('{{content}}', content))
send_mail(template.replace("{{content}}", content), default_config)
with open('conf.ini', 'w') as configfile:
with open("conf.ini", "w", encoding="utf-8") as configfile:
parser.write(configfile)
def get_last_release(project):
url = 'https://api.github.com/repos/{}/releases/latest'.format(project)
result = requests.get(url)
url = f"https://api.github.com/repos/{project}/releases/latest"
result = requests.get(url, timeout=10)
print(project)
print(url)
release = result.json()
release_tag = release['tag_name']
published_date = release['published_at']
release_tag = release["tag_name"]
published_date = release["published_at"]
# body = release['body']
release_url = release['html_url']
release_url = release["html_url"]
return {'release_tag': release_tag,
'published_date': published_date,
# 'body': body,
'project_name': project,
'release_url': release_url}
return {
"release_tag": release_tag,
"published_date": published_date,
# 'body': body,
"project_name": project,
"release_url": release_url,
}
def get_html_project_link(el):
project_url = f'https://github.com/{el["project_name"]}'
return f'<a href="{project_url}" target="_blank">{el["project_name"]}</a>'
def get_html_release_link(el):
return f'<a href="{el["release_url"]}" target="_blank">{el["release_tag"]}</a>'
def send_mail(content, config):
smtp_port = config.get("smtp_port")
smtp_server = config.get("smtp_server")
sender_email = config.get("sender_email")
receiver_email = config.get("receiver_email")
def send_mail(content):
message = MIMEMultipart("alternative")
message["Subject"] = "New Github releases"
message["From"] = SENDER_EMAIL
message["To"] = RECEIVER_EMAIL
message["From"] = sender_email
message["To"] = receiver_email
# part1 = MIMEText(text, "plain")
part2 = MIMEText(content, "html")
@@ -105,11 +140,13 @@ def send_mail(content):
# message.attach(part1)
message.attach(part2)
with smtplib.SMTP(SMTP_SERVER, SMTP_PORT) as server:
server.sendmail(SENDER_EMAIL, RECEIVER_EMAIL, message.as_string())
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.sendmail(sender_email, receiver_email, message.as_string())
def convert_date(date: str, dest_format="%d %b %Y at %H:%M") -> str:
return datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ").strftime(dest_format)
def convert_date(date: str, format='%d %b %Y at %H:%M') -> str:
return datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ").strftime(format)
if __name__ == "__main__":
main()

9
ofelia.ini Normal file
View File

@@ -0,0 +1,9 @@
[global]
smtp-host = mailpit
smtp-port = 1025
email-to = max@ence.fr
email-from = ofelia@container.sh
[job-run "notifier"]
schedule = @every 30s
container = github-release-notifier

BIN
pit.db

Binary file not shown.

735
pixi.lock Normal file
View File

@@ -0,0 +1,735 @@
version: 3
metadata:
content_hash:
linux-64: e90c2ee71ad70fc0a1c8302029533a7d1498f2bffcd0eaa8d2934700e775dc1d
channels:
- url: https://conda.anaconda.org/conda-forge/
used_env_vars: []
platforms:
- linux-64
sources: []
time_metadata: null
git_metadata: null
inputs_metadata: null
custom_metadata: null
package:
- platform: linux-64
name: _libgcc_mutex
version: '0.1'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2
hash:
md5: d7c89558ba9fa0495403155b64376d81
sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726
build: conda_forge
arch: x86_64
subdir: linux-64
build_number: 0
license: None
size: 2562
timestamp: 1578324546067
- platform: linux-64
name: _openmp_mutex
version: '4.5'
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
- libgomp >=7.5.0
url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2
hash:
md5: 73aaf86a425cc6e73fcf236a5a46396d
sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22
build: 2_gnu
arch: x86_64
subdir: linux-64
build_number: 16
constrains:
- openmp_impl 9999
license: BSD-3-Clause
license_family: BSD
size: 23621
timestamp: 1650670423406
- platform: linux-64
name: black
version: 23.11.0
category: main
manager: conda
dependencies:
- click >=8.0.0
- mypy_extensions >=0.4.3
- packaging >=22.0
- pathspec >=0.9
- platformdirs >=2
- python >=3.12,<3.13.0a0
- python_abi 3.12.* *_cp312
url: https://conda.anaconda.org/conda-forge/linux-64/black-23.11.0-py312h7900ff3_0.conda
hash:
md5: a0b80edb299377d3fa8233d43a19f11e
sha256: 1b6cd73fb6d39d45e2010a8cf2c2b82ab6d36323f4f9717f1550e80ca802f986
build: py312h7900ff3_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
size: 366103
timestamp: 1701335795851
- platform: linux-64
name: brotli-python
version: 1.1.0
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libstdcxx-ng >=12
- python >=3.12.0rc3,<3.13.0a0
- python_abi 3.12.* *_cp312
url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py312h30efb56_1.conda
hash:
md5: 45801a89533d3336a365284d93298e36
sha256: b68706698b6ac0d31196a8bcb061f0d1f35264bcd967ea45e03e108149a74c6f
build: py312h30efb56_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- libbrotlicommon 1.1.0 hd590300_1
license: MIT
license_family: MIT
size: 350604
timestamp: 1695990206327
- platform: linux-64
name: bzip2
version: 1.0.8
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda
hash:
md5: 69b8b6202a07720f448be700e300ccf4
sha256: 242c0c324507ee172c0e0dd2045814e746bb303d1eb78870d182ceb0abc726a8
build: hd590300_5
arch: x86_64
subdir: linux-64
build_number: 5
license: bzip2-1.0.6
license_family: BSD
size: 254228
timestamp: 1699279927352
- platform: linux-64
name: ca-certificates
version: 2023.11.17
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.11.17-hbcca054_0.conda
hash:
md5: 01ffc8d36f9eba0ce0b3c1955fa780ee
sha256: fb4b9f4b7d885002db0b93e22f44b5b03791ef3d4efdc9d0662185a0faafd6b6
build: hbcca054_0
arch: x86_64
subdir: linux-64
build_number: 0
license: ISC
size: 154117
timestamp: 1700280881924
- platform: linux-64
name: certifi
version: 2023.11.17
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/certifi-2023.11.17-pyhd8ed1ab_0.conda
hash:
md5: 2011bcf45376341dd1d690263fdbc789
sha256: afa22b77128a812cb57bc707c297d926561bd225a3d9dd74205d87a3b2d14a96
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: ISC
noarch: python
size: 158939
timestamp: 1700303562512
- platform: linux-64
name: charset-normalizer
version: 3.3.2
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda
hash:
md5: 7f4a9e3fcff3f6356ae99244a014da6a
sha256: 20cae47d31fdd58d99c4d2e65fbdcefa0b0de0c84e455ba9d6356a4bdbc4b5b9
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 46597
timestamp: 1698833765762
- platform: linux-64
name: click
version: 8.1.7
category: main
manager: conda
dependencies:
- __unix
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda
hash:
md5: f3ad426304898027fc619827ff428eca
sha256: f0016cbab6ac4138a429e28dbcb904a90305b34b3fe41a9b89d697c90401caec
build: unix_pyh707e725_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 84437
timestamp: 1692311973840
- platform: linux-64
name: idna
version: '3.6'
category: main
manager: conda
dependencies:
- python >=3.6
url: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda
hash:
md5: 1a76f09108576397c41c0b0c5bd84134
sha256: 6ee4c986d69ce61e60a20b2459b6f2027baeba153f0a64995fd3cb47c2cc7e07
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 50124
timestamp: 1701027126206
- platform: linux-64
name: ld_impl_linux-64
version: '2.40'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda
hash:
md5: 7aca3059a1729aa76c597603f10b0dd3
sha256: f6cc89d887555912d6c61b295d398cff9ec982a3417d38025c45d5dd9b9e79cd
build: h41732ed_0
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- binutils_impl_linux-64 2.40
license: GPL-3.0-only
license_family: GPL
size: 704696
timestamp: 1674833944779
- platform: linux-64
name: libexpat
version: 2.5.0
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda
hash:
md5: 6305a3dd2752c76335295da4e581f2fd
sha256: 74c98a563777ae2ad71f1f74d458a8ab043cee4a513467c159ccf159d0e461f3
build: hcb278e6_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- expat 2.5.0.*
license: MIT
license_family: MIT
size: 77980
timestamp: 1680190528313
- platform: linux-64
name: libffi
version: 3.4.2
category: main
manager: conda
dependencies:
- libgcc-ng >=9.4.0
url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2
hash:
md5: d645c6d2ac96843a2bfaccd2d62b3ac3
sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e
build: h7f98852_5
arch: x86_64
subdir: linux-64
build_number: 5
license: MIT
license_family: MIT
size: 58292
timestamp: 1636488182923
- platform: linux-64
name: libgcc-ng
version: 13.2.0
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
- _openmp_mutex >=4.5
url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_3.conda
hash:
md5: 23fdf1fef05baeb7eadc2aed5fb0011f
sha256: 5e88f658e07a30ab41b154b42c59f079b168acfa9551a75bdc972099453f4105
build: h807b86a_3
arch: x86_64
subdir: linux-64
build_number: 3
constrains:
- libgomp 13.2.0 h807b86a_3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 773629
timestamp: 1699753612541
- platform: linux-64
name: libgomp
version: 13.2.0
category: main
manager: conda
dependencies:
- _libgcc_mutex 0.1 conda_forge
url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_3.conda
hash:
md5: 7124cbb46b13d395bdde68f2d215c989
sha256: 6ebedee39b6bbbc969715d0d7fa4b381cce67e1139862604ffa393f821c08e81
build: h807b86a_3
arch: x86_64
subdir: linux-64
build_number: 3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 421834
timestamp: 1699753531479
- platform: linux-64
name: libnsl
version: 2.0.1
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda
hash:
md5: 30fd6e37fe21f86f4bd26d6ee73eeec7
sha256: 26d77a3bb4dceeedc2a41bd688564fe71bf2d149fdcf117049970bc02ff1add6
build: hd590300_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LGPL-2.1-only
license_family: GPL
size: 33408
timestamp: 1697359010159
- platform: linux-64
name: libsqlite
version: 3.44.2
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libzlib >=1.2.13,<1.3.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.44.2-h2797004_0.conda
hash:
md5: 3b6a9f225c3dbe0d24f4fedd4625c5bf
sha256: ee2c4d724a3ed60d5b458864d66122fb84c6ce1df62f735f90d8db17b66cd88a
build: h2797004_0
arch: x86_64
subdir: linux-64
build_number: 0
license: Unlicense
size: 845830
timestamp: 1700863204572
- platform: linux-64
name: libstdcxx-ng
version: 13.2.0
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_3.conda
hash:
md5: 937eaed008f6bf2191c5fe76f87755e9
sha256: 6c6c49efedcc5709a66f19fb6b26b69c6a5245310fd1d9a901fd5e38aaf7f882
build: h7e041cc_3
arch: x86_64
subdir: linux-64
build_number: 3
license: GPL-3.0-only WITH GCC-exception-3.1
license_family: GPL
size: 3842940
timestamp: 1699753676253
- platform: linux-64
name: libuuid
version: 2.38.1
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda
hash:
md5: 40b61aab5c7ba9ff276c41cfffe6b80b
sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18
build: h0b41bf4_0
arch: x86_64
subdir: linux-64
build_number: 0
license: BSD-3-Clause
license_family: BSD
size: 33601
timestamp: 1680112270483
- platform: linux-64
name: libzlib
version: 1.2.13
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda
hash:
md5: f36c115f1ee199da648e0597ec2047ad
sha256: 370c7c5893b737596fd6ca0d9190c9715d89d888b8c88537ae1ef168c25e82e4
build: hd590300_5
arch: x86_64
subdir: linux-64
build_number: 5
constrains:
- zlib 1.2.13 *_5
license: Zlib
license_family: Other
size: 61588
timestamp: 1686575217516
- platform: linux-64
name: mypy_extensions
version: 1.0.0
category: main
manager: conda
dependencies:
- python >=3.5
url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda
hash:
md5: 4eccaeba205f0aed9ac3a9ea58568ca3
sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3
build: pyha770c72_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 10492
timestamp: 1675543414256
- platform: linux-64
name: ncurses
version: '6.4'
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4-h59595ed_2.conda
hash:
md5: 7dbaa197d7ba6032caf7ae7f32c1efa0
sha256: 91cc03f14caf96243cead96c76fe91ab5925a695d892e83285461fb927dece5e
build: h59595ed_2
arch: x86_64
subdir: linux-64
build_number: 2
license: X11 AND BSD-3-Clause
size: 884434
timestamp: 1698751260967
- platform: linux-64
name: openssl
version: 3.2.0
category: main
manager: conda
dependencies:
- ca-certificates
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.0-hd590300_1.conda
hash:
md5: 603827b39ea2b835268adb8c821b8570
sha256: 80efc6f429bd8e622d999652e5cba2ca56fcdb9c16a439d2ce9b4313116e4a87
build: hd590300_1
arch: x86_64
subdir: linux-64
build_number: 1
constrains:
- pyopenssl >=22.1
license: Apache-2.0
license_family: Apache
size: 2854103
timestamp: 1701162437033
- platform: linux-64
name: packaging
version: '23.2'
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda
hash:
md5: 79002079284aa895f883c6b7f3f88fd6
sha256: 69b3ace6cca2dab9047b2c24926077d81d236bef45329d264b394001e3c3e52f
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: Apache-2.0
license_family: APACHE
noarch: python
size: 49452
timestamp: 1696202521121
- platform: linux-64
name: pathspec
version: 0.12.1
category: main
manager: conda
dependencies:
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda
hash:
md5: 17064acba08d3686f1135b5ec1b32b12
sha256: 4e534e66bfe8b1e035d2169d0e5b185450546b17e36764272863e22e0370be4d
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MPL-2.0
license_family: MOZILLA
noarch: python
size: 41173
timestamp: 1702250135032
- platform: linux-64
name: platformdirs
version: 4.1.0
category: main
manager: conda
dependencies:
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.1.0-pyhd8ed1ab_0.conda
hash:
md5: 45a5065664da0d1dfa8f8cd2eaf05ab9
sha256: 9e4ff17ce802159ed31344eb913eaa877688226765b77947b102b42255a53853
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 20058
timestamp: 1701708396900
- platform: linux-64
name: pysocks
version: 1.7.1
category: main
manager: conda
dependencies:
- __unix
- python >=3.8
url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2
hash:
md5: 2a7de29fb590ca14b5243c4c812c8025
sha256: a42f826e958a8d22e65b3394f437af7332610e43ee313393d1cf143f0a2d274b
build: pyha2e5f31_6
arch: x86_64
subdir: linux-64
build_number: 6
license: BSD-3-Clause
license_family: BSD
noarch: python
size: 18981
timestamp: 1661604969727
- platform: linux-64
name: python
version: 3.12.0
category: main
manager: conda
dependencies:
- bzip2 >=1.0.8,<2.0a0
- ld_impl_linux-64 >=2.36.1
- libexpat >=2.5.0,<3.0a0
- libffi >=3.4,<4.0a0
- libgcc-ng >=12
- libnsl >=2.0.0,<2.1.0a0
- libsqlite >=3.43.0,<4.0a0
- libuuid >=2.38.1,<3.0a0
- libzlib >=1.2.13,<1.3.0a0
- ncurses >=6.4,<7.0a0
- openssl >=3.1.3,<4.0a0
- readline >=8.2,<9.0a0
- tk >=8.6.13,<8.7.0a0
- tzdata
- xz >=5.2.6,<6.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.0-hab00c5b_0_cpython.conda
hash:
md5: 7f97faab5bebcc2580f4f299285323da
sha256: 5398ebae6a1ccbfd3f76361eac75f3ac071527a8072627c4bf9008c689034f48
build: hab00c5b_0_cpython
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- python_abi 3.12.* *_cp312
license: Python-2.0
size: 32123473
timestamp: 1696324522323
- platform: linux-64
name: python_abi
version: '3.12'
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda
hash:
md5: dccc2d142812964fcc6abdc97b672dff
sha256: 182a329de10a4165f6e8a3804caf751f918f6ea6176dd4e5abcdae1ed3095bf6
build: 4_cp312
arch: x86_64
subdir: linux-64
build_number: 4
constrains:
- python 3.12.* *_cpython
license: BSD-3-Clause
license_family: BSD
size: 6385
timestamp: 1695147396604
- platform: linux-64
name: readline
version: '8.2'
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- ncurses >=6.3,<7.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda
hash:
md5: 47d31b792659ce70f470b5c82fdfb7a4
sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7
build: h8228510_1
arch: x86_64
subdir: linux-64
build_number: 1
license: GPL-3.0-only
license_family: GPL
size: 281456
timestamp: 1679532220005
- platform: linux-64
name: requests
version: 2.31.0
category: main
manager: conda
dependencies:
- certifi >=2017.4.17
- charset-normalizer >=2,<4
- idna >=2.5,<4
- python >=3.7
- urllib3 >=1.21.1,<3
url: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda
hash:
md5: a30144e4156cdbb236f99ebb49828f8b
sha256: 9f629d6fd3c8ac5f2a198639fe7af87c4db2ac9235279164bfe0fcb49d8c4bad
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
constrains:
- chardet >=3.0.2,<6
license: Apache-2.0
license_family: APACHE
noarch: python
size: 56690
timestamp: 1684774408600
- platform: linux-64
name: tk
version: 8.6.13
category: main
manager: conda
dependencies:
- libgcc-ng >=12
- libzlib >=1.2.13,<1.3.0a0
url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda
hash:
md5: d453b98d9c83e71da0741bb0ff4d76bc
sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e
build: noxft_h4845f30_101
arch: x86_64
subdir: linux-64
build_number: 101
license: TCL
license_family: BSD
size: 3318875
timestamp: 1699202167581
- platform: linux-64
name: tzdata
version: 2023c
category: main
manager: conda
dependencies: []
url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2023c-h71feb2d_0.conda
hash:
md5: 939e3e74d8be4dac89ce83b20de2492a
sha256: 0449138224adfa125b220154408419ec37c06b0b49f63c5954724325903ecf55
build: h71feb2d_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LicenseRef-Public-Domain
noarch: generic
size: 117580
timestamp: 1680041306008
- platform: linux-64
name: urllib3
version: 2.1.0
category: main
manager: conda
dependencies:
- brotli-python >=1.0.9
- pysocks >=1.5.6,<2.0,!=1.5.7
- python >=3.7
url: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.1.0-pyhd8ed1ab_0.conda
hash:
md5: f8ced8ee63830dec7ecc1be048d1470a
sha256: eff5029820b4eaeab3a291a39854a6cd8fc8c4216264087f68c2d8d59822c869
build: pyhd8ed1ab_0
arch: x86_64
subdir: linux-64
build_number: 0
license: MIT
license_family: MIT
noarch: python
size: 85324
timestamp: 1699933655057
- platform: linux-64
name: xz
version: 5.2.6
category: main
manager: conda
dependencies:
- libgcc-ng >=12
url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2
hash:
md5: 2161070d867d1b1204ea749c8eec4ef0
sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162
build: h166bdaf_0
arch: x86_64
subdir: linux-64
build_number: 0
license: LGPL-2.1 and GPL-2.0
size: 418368
timestamp: 1660346797927

17
pixi.toml Normal file
View File

@@ -0,0 +1,17 @@
[project]
name = "github-release-notifier"
version = "1"
description = "Send mail notification on new released versions of Github projects"
authors = ["Maxence G. de Montauzan <maxence@gdemontauzan.fr>"]
channels = ["conda-forge"]
platforms = ["linux-64"]
repository = "https://github.com/MaxenceG2M/github-release-notifier"
[tasks]
[dependencies]
python = ">=3.12.0,<3.13"
requests = ">=2.31.0,<2.32"
[build-dependencies]
black = ">=23.11.0,<23.12"

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
requests
pre-commit
black

File diff suppressed because one or more lines are too long