Compare commits
8 Commits
1c9b946e49
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
cc640700a4
|
|||
|
a84fc769ac
|
|||
|
2b00dcc305
|
|||
|
cc526eb592
|
|||
|
b9616bb19e
|
|||
|
63e72559be
|
|||
|
0b543c5b70
|
|||
|
4de3431e50
|
@@ -56,6 +56,21 @@ steps:
|
|||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
- name: gather-digests
|
||||||
|
image: quay.io/skopeo/stable:latest
|
||||||
|
environment:
|
||||||
|
DOCKER_USER:
|
||||||
|
from_secret: registry_username
|
||||||
|
DOCKER_PASS:
|
||||||
|
from_secret: registry_password
|
||||||
|
when:
|
||||||
|
- event: push
|
||||||
|
branch: main
|
||||||
|
commands:
|
||||||
|
- dnf install -y jq
|
||||||
|
- skopeo login dev.shielddagger.com --username $DOCKER_USER --password $DOCKER_PASS
|
||||||
|
- skopeo inspect --raw docker://dev.shielddagger.com/opensource/discord-notifier:latest | jq -r .'manifests[] | select(.platform.architecture=="arm64").digest' > digest-arm64
|
||||||
|
- skopeo inspect --raw docker://dev.shielddagger.com/opensource/discord-notifier:latest | jq -r .'manifests[] | select(.platform.architecture=="amd64").digest' > digest-amd64
|
||||||
- name: image-scan
|
- name: image-scan
|
||||||
image: aquasec/trivy
|
image: aquasec/trivy
|
||||||
environment:
|
environment:
|
||||||
@@ -67,7 +82,8 @@ steps:
|
|||||||
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db
|
TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db
|
||||||
TRIVY_CHECKS_BUNDLE_REPOSITORY: public.ecr.aws/aquasecurity/trivy-checks
|
TRIVY_CHECKS_BUNDLE_REPOSITORY: public.ecr.aws/aquasecurity/trivy-checks
|
||||||
commands:
|
commands:
|
||||||
- trivy image dev.shielddagger.com/opensource/discord-notifier:latest --exit-code 1 --username $TRIVY_USER --severity HIGH,CRITICAL
|
- export ARM64_DIGEST=$(cat digest-arm64)
|
||||||
|
- trivy image --platform linux/arm64 --debug dev.shielddagger.com/opensource/discord-notifier@$ARM64_DIGEST --exit-code 1 --username $TRIVY_USER --severity HIGH,CRITICAL
|
||||||
when:
|
when:
|
||||||
- event: push
|
- event: push
|
||||||
branch: main
|
branch: main
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ from urllib.parse import urljoin, urlparse
|
|||||||
from requests import Session
|
from requests import Session
|
||||||
from requests.models import Response
|
from requests.models import Response
|
||||||
|
|
||||||
|
logfile_webhook = DiscordWebhook(environ["PLUGIN_WEBHOOK_URL"], rate_limit_retry=True)
|
||||||
|
logfile_webhook.username = "Woodpecker CI"
|
||||||
|
logfile_webhook.avatar_url = "https://ci.shielddagger.com/favicons/favicon-dark-error.png"
|
||||||
|
|
||||||
|
webhook = DiscordWebhook(environ["PLUGIN_WEBHOOK_URL"], rate_limit_retry=True)
|
||||||
|
webhook.username = "Woodpecker CI"
|
||||||
|
|
||||||
|
|
||||||
class APISession(Session):
|
class APISession(Session):
|
||||||
def __init__(self, base_url) -> None:
|
def __init__(self, base_url) -> None:
|
||||||
@@ -19,13 +26,44 @@ class APISession(Session):
|
|||||||
def request(self, method: str | bytes, url: str | bytes, *args, **kwargs) -> Response:
|
def request(self, method: str | bytes, url: str | bytes, *args, **kwargs) -> Response:
|
||||||
url = urljoin(self.base_url, url)
|
url = urljoin(self.base_url, url)
|
||||||
return super().request(method, url, *args, **kwargs)
|
return super().request(method, url, *args, **kwargs)
|
||||||
|
try:
|
||||||
|
ci_client = APISession(environ["PLUGIN_WOODPECKER_URL"].rstrip("/"))
|
||||||
|
ci_client.headers.setdefault("Authorization", f"Bearer {environ["PLUGIN_WOODPECKER_TOKEN"]}")
|
||||||
|
except KeyError:
|
||||||
|
webhook.add_embed(DiscordEmbed(
|
||||||
|
"API Error",
|
||||||
|
"API access has not been configured.\n"\
|
||||||
|
"As a result, Discord Notifier is unable to retrieve job information like logs or status.\n"\
|
||||||
|
"Please use the `woodpecker_url` and `woodpecker_token` settings to allow API access.",
|
||||||
|
color="ED4345",
|
||||||
|
timestamp=datetime.now(UTC),
|
||||||
|
footer={
|
||||||
|
"text": "Discord Notifier",
|
||||||
|
"icon_url": "https://dev.shielddagger.com/repo-avatars/273e88fa2afde290121dc7b5987dc366b88325f147bf1e5766bca26296bbc1f9"
|
||||||
|
}
|
||||||
|
))
|
||||||
|
webhook.execute()
|
||||||
|
exit(1)
|
||||||
|
|
||||||
logfile_webhook = None
|
pipeline_url = urlparse(environ["CI_PIPELINE_URL"]).path.lstrip("/").split("/")
|
||||||
webhook = DiscordWebhook(environ["PLUGIN_WEBHOOK_URL"], rate_limit_retry=True)
|
repo_id = pipeline_url[1]
|
||||||
|
pipeline_number = pipeline_url[3]
|
||||||
|
|
||||||
success = environ["CI_PIPELINE_STATUS"] != "failure"
|
pipeline_info = ci_client.get(f"/api/repos/{repo_id}/pipelines/{pipeline_number}").json()
|
||||||
|
success = None
|
||||||
|
for workflow in pipeline_info["workflows"]:
|
||||||
|
if workflow["name"] != environ["CI_WORKFLOW_NAME"]:
|
||||||
|
continue
|
||||||
|
for step in workflow["children"]:
|
||||||
|
if step["state"] != "failure":
|
||||||
|
continue
|
||||||
|
loginfo = ci_client.get(f"/api/repos/{repo_id}/logs/{pipeline_number}/{step['id']}").json()
|
||||||
|
logdata = b""
|
||||||
|
for logline in loginfo:
|
||||||
|
logdata += b64decode(logline["data"]) + b"\n"
|
||||||
|
logfile_webhook.add_file(logdata, f"{step['name']}.ansi")
|
||||||
|
success = all(step["state"] != "failure" for step in workflow["children"])
|
||||||
|
|
||||||
webhook.username = "Woodpecker CI"
|
|
||||||
webhook.avatar_url = "https://ci.shielddagger.com/favicons/favicon-dark-success.png" if success else \
|
webhook.avatar_url = "https://ci.shielddagger.com/favicons/favicon-dark-success.png" if success else \
|
||||||
"https://ci.shielddagger.com/favicons/favicon-dark-error.png"
|
"https://ci.shielddagger.com/favicons/favicon-dark-error.png"
|
||||||
|
|
||||||
@@ -39,8 +77,8 @@ webhook.add_embed(DiscordEmbed(
|
|||||||
"url": environ["CI_REPO_URL"]
|
"url": environ["CI_REPO_URL"]
|
||||||
},
|
},
|
||||||
footer={
|
footer={
|
||||||
"text": environ["CI_COMMIT_AUTHOR"],
|
"text": environ.get("CI_COMMIT_AUTHOR", "Woodpecker"),
|
||||||
"icon_url": environ["CI_COMMIT_AUTHOR_AVATAR"]
|
"icon_url": environ.get("CI_COMMIT_AUTHOR_AVATAR", "https://ci.shielddagger.com/favicons/favicon-dark-default.png")
|
||||||
},
|
},
|
||||||
thumbnail={
|
thumbnail={
|
||||||
"url": getenv("PLUGIN_ICON_URL"),
|
"url": getenv("PLUGIN_ICON_URL"),
|
||||||
@@ -65,47 +103,10 @@ webhook.add_embed(DiscordEmbed(
|
|||||||
}]
|
}]
|
||||||
))
|
))
|
||||||
|
|
||||||
try:
|
|
||||||
if not success:
|
|
||||||
logfile_webhook = DiscordWebhook(environ["PLUGIN_WEBHOOK_URL"], rate_limit_retry=True)
|
|
||||||
logfile_webhook.username = "Woodpecker CI"
|
|
||||||
logfile_webhook.avatar_url = "https://ci.shielddagger.com/favicons/favicon-dark-error.png"
|
|
||||||
with APISession(environ["PLUGIN_WOODPECKER_URL"].rstrip("/")) as client:
|
|
||||||
client.headers.setdefault("Authorization", f"Bearer {environ["PLUGIN_WOODPECKER_TOKEN"]}")
|
|
||||||
|
|
||||||
pipeline_url = urlparse(environ["CI_PIPELINE_URL"]).path.lstrip("/").split("/")
|
|
||||||
repo_id = pipeline_url[1]
|
|
||||||
pipeline_number = pipeline_url[3]
|
|
||||||
|
|
||||||
pipeline_info = client.get(f"/api/repos/{repo_id}/pipelines/{pipeline_number}").json()
|
|
||||||
for workflow in pipeline_info["workflows"]:
|
|
||||||
if workflow["name"] != environ["CI_WORKFLOW_NAME"]:
|
|
||||||
continue
|
|
||||||
for step in workflow["children"]:
|
|
||||||
if step["state"] != "failure":
|
|
||||||
continue
|
|
||||||
loginfo = client.get(f"/api/repos/{repo_id}/logs/{pipeline_number}/{step['id']}").json()
|
|
||||||
logdata = b""
|
|
||||||
for logline in loginfo:
|
|
||||||
logdata += b64decode(logline["data"]) + b"\n"
|
|
||||||
logfile_webhook.add_file(logdata, f"{step['name']}.ansi")
|
|
||||||
except KeyError:
|
|
||||||
webhook.add_embed(DiscordEmbed(
|
|
||||||
"API Error",
|
|
||||||
"API access has not been configured.\n"\
|
|
||||||
"As a result, Discord Notifier is unable to retrieve failed job logs to attach here.\n"\
|
|
||||||
"Please use the `woodpecker_url` and `woodpecker_token` settings to allow API access.",
|
|
||||||
color="ED4345",
|
|
||||||
timestamp=datetime.now(UTC),
|
|
||||||
footer={
|
|
||||||
"text": "Discord Notifier",
|
|
||||||
"icon_url": "https://dev.shielddagger.com/repo-avatars/273e88fa2afde290121dc7b5987dc366b88325f147bf1e5766bca26296bbc1f9"
|
|
||||||
}
|
|
||||||
))
|
|
||||||
|
|
||||||
pprint(webhook.json)
|
pprint(webhook.json)
|
||||||
webhook.execute()
|
webhook.execute()
|
||||||
|
|
||||||
if logfile_webhook is not None:
|
if not success:
|
||||||
pprint(logfile_webhook.json)
|
pprint(logfile_webhook.json)
|
||||||
logfile_webhook.execute()
|
logfile_webhook.execute()
|
||||||
|
|||||||
Reference in New Issue
Block a user