CI/CD hardening: lint, secret scan, coverage gate, auto CVE-fix PRs, GHCR + GitHub mirror publishing (#32)
CI / build-and-scan (push) Successful in 1m37s
CI / build-and-scan (push) Successful in 1m37s
- release changelog: commits rendered as description (link), divider lines dropped - gitleaks secret scan and hadolint on every push/PR - ruff lint/format gate (Python repos) with a pytest --cov-fail-under gate - scheduled CRITICAL Trivy failures attempt an apk upgrade rebuild and open a follow-up PR if it clears the finding, instead of just failing red - images also published to ghcr.io/djeex/<repo> - a matching GitHub Release is created on the GitHub mirror, with a notice pointing back to this repo as the source of truth
This commit was merged in pull request #32.
This commit is contained in:
+43
-19
@@ -1,15 +1,29 @@
|
||||
import time
|
||||
import logging
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
from env_config import (
|
||||
DISCORD_WEBHOOK_URL, DISCORD_SERVER_NAME, DISCORD_ROLE_MAP, TEST_MODE, currency,
|
||||
in_stock_title, out_of_stock_title, sku_change_title,
|
||||
buy_now, price_label, time_label, footer, sku_description, imminent_drop
|
||||
DISCORD_ROLE_MAP,
|
||||
DISCORD_SERVER_NAME,
|
||||
DISCORD_WEBHOOK_URL,
|
||||
TEST_MODE,
|
||||
buy_now,
|
||||
currency,
|
||||
footer,
|
||||
imminent_drop,
|
||||
in_stock_title,
|
||||
out_of_stock_title,
|
||||
price_label,
|
||||
sku_change_title,
|
||||
sku_description,
|
||||
time_label,
|
||||
)
|
||||
|
||||
AVATAR = "https://git.djeex.fr/Djeex/nvidia-stock-bot/raw/branch/main/assets/img/ds_wh_pp.jpg"
|
||||
THUMBNAIL = "https://git.djeex.fr/Djeex/nvidia-stock-bot/raw/branch/main/assets/img/RTX5000.jpg"
|
||||
|
||||
|
||||
# In stock
|
||||
def send_discord_notification(gpu_name, product_link, products_price):
|
||||
timestamp = int(time.time())
|
||||
@@ -24,17 +38,20 @@ def send_discord_notification(gpu_name, product_link, products_price):
|
||||
"author": {"name": "Nvidia Founder Editions"},
|
||||
"fields": [
|
||||
{"name": price_label, "value": f"`{currency}{products_price}`", "inline": True},
|
||||
{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True}
|
||||
{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True},
|
||||
],
|
||||
"description": buy_now.format(product_link=product_link),
|
||||
"footer": {"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME), "icon_url": AVATAR}
|
||||
"footer": {
|
||||
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
|
||||
"icon_url": AVATAR,
|
||||
},
|
||||
}
|
||||
|
||||
payload = {
|
||||
"content": DISCORD_ROLE_MAP.get(gpu_name, "@everyone"),
|
||||
"username": "NviBot",
|
||||
"avatar_url": AVATAR,
|
||||
"embeds": [embed]
|
||||
"embeds": [embed],
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -46,6 +63,7 @@ def send_discord_notification(gpu_name, product_link, products_price):
|
||||
except Exception as e:
|
||||
logging.error(f"🚨 Error sending webhook: {e}")
|
||||
|
||||
|
||||
# Out of stock
|
||||
def send_out_of_stock_notification(gpu_name, product_link, products_price):
|
||||
timestamp = int(time.time())
|
||||
@@ -59,15 +77,16 @@ def send_out_of_stock_notification(gpu_name, product_link, products_price):
|
||||
"thumbnail": {"url": THUMBNAIL},
|
||||
"url": product_link,
|
||||
"author": {"name": "Nvidia Founder Editions"},
|
||||
"footer": {"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME), "icon_url": AVATAR},
|
||||
"fields": [{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True}]
|
||||
"footer": {
|
||||
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
|
||||
"icon_url": AVATAR,
|
||||
},
|
||||
"fields": [
|
||||
{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True}
|
||||
],
|
||||
}
|
||||
|
||||
payload = {
|
||||
"username": "NviBot",
|
||||
"avatar_url": AVATAR,
|
||||
"embeds": [embed]
|
||||
}
|
||||
payload = {"username": "NviBot", "avatar_url": AVATAR, "embeds": [embed]}
|
||||
|
||||
try:
|
||||
response = requests.post(DISCORD_WEBHOOK_URL, json=payload)
|
||||
@@ -78,6 +97,7 @@ def send_out_of_stock_notification(gpu_name, product_link, products_price):
|
||||
except Exception as e:
|
||||
logging.error(f"🚨 Error sending webhook: {e}")
|
||||
|
||||
|
||||
# SKU change
|
||||
def send_sku_change_notification(gpu_name, old_sku, new_sku, product_link):
|
||||
timestamp = int(time.time())
|
||||
@@ -90,15 +110,20 @@ def send_sku_change_notification(gpu_name, old_sku, new_sku, product_link):
|
||||
"url": product_link,
|
||||
"description": sku_description.format(old_sku=old_sku, new_sku=new_sku),
|
||||
"color": 16776960,
|
||||
"footer": {"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME), "icon_url": AVATAR},
|
||||
"fields": [{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True}]
|
||||
"footer": {
|
||||
"text": footer.format(DISCORD_SERVER_NAME=DISCORD_SERVER_NAME),
|
||||
"icon_url": AVATAR,
|
||||
},
|
||||
"fields": [
|
||||
{"name": time_label, "value": f"<t:{timestamp}:d> <t:{timestamp}:T>", "inline": True}
|
||||
],
|
||||
}
|
||||
|
||||
payload = {
|
||||
"content": imminent_drop.format(DISCORD_ROLE=DISCORD_ROLE_MAP.get(gpu_name, '@everyone')),
|
||||
"content": imminent_drop.format(DISCORD_ROLE=DISCORD_ROLE_MAP.get(gpu_name, "@everyone")),
|
||||
"username": "NviBot",
|
||||
"avatar_url": AVATAR,
|
||||
"embeds": [embed]
|
||||
"embeds": [embed],
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -109,4 +134,3 @@ def send_sku_change_notification(gpu_name, old_sku, new_sku, product_link):
|
||||
logging.error(f"❌ Webhook error: {response.status_code} - {response.text}")
|
||||
except Exception as e:
|
||||
logging.error(f"🚨 Error sending webhook: {e}")
|
||||
|
||||
Reference in New Issue
Block a user