fix: CustomException.msg missing #250
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Python CI | |
on: | |
push: | |
branches: | |
- "*" | |
tags: | |
- '[0-9]+.[0-9]+.[0-9]+' | |
paths: | |
- "src/**/*.py" | |
- "requirements.txt" | |
- ".dockerignore" | |
- "./.docker/Dockerfile" | |
- "docker-compose*.yml" | |
- ".github/workflows/python.yml" | |
pull_request: | |
types: [opened, synchronize] | |
branches: | |
- "*" | |
paths: | |
- "src/**/*.py" | |
- "tests/**/*.py" | |
- "requirements.txt" | |
- ".dockerignore" | |
- "./.docker/Dockerfile" | |
- "docker-compose*.yml" | |
- ".github/workflows/python.yml" | |
workflow_dispatch: | |
env: | |
MODULE_NAME: "pyramid" | |
SRC: "./src" | |
TEST_DIR: "./tests" | |
REGISTRY_IMAGE: ${{ vars.DOCKERHUB_USERNAME }}/${{ vars.DOCKERHUB_REPO_NAME }} | |
REGISTRY_IMAGE_PRIVATE: ${{ vars.DOCKER_REGISTRY_PRIVATE_URL }}/${{ github.actor }}/${{ github.event.repository.name }} | |
jobs: | |
info: | |
name: "Informations" | |
runs-on: ubuntu-latest | |
outputs: | |
project_version: ${{ steps.environment.outputs.project_version }} | |
environment: ${{ steps.environment.outputs.git_environment }} | |
docker_tag: ${{ steps.environment.outputs.docker_tag }} | |
commit_id: ${{ steps.environment.outputs.commit_id }} | |
last_release_ref: ${{ steps.last_release.result.last_release_ref }} | |
changelog: ${{ steps.changelog.outputs.changelog }} | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Define build variables | |
id: environment | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const refType = '${{ github.ref_type }}'; | |
const ref = context.ref; | |
const sha = context.sha; | |
const shortSha = sha.slice(0, 7); | |
let dockerTag; | |
let gitEnvironment; | |
let projectVersion; | |
if (refType === 'tag') { | |
dockerTag = 'latest'; | |
gitEnvironment = 'production'; | |
projectVersion = '${{ github.ref_name }}'; | |
} else if (ref === 'refs/heads/main') { | |
dockerTag = 'pre-prod'; | |
gitEnvironment = 'pre-production'; | |
projectVersion = `${shortSha}`; | |
} else { | |
dockerTag = 'staging'; | |
gitEnvironment = 'staging'; | |
projectVersion = `${shortSha}`; | |
} | |
const reset = "\x1b[0m"; | |
const textColor = "\x1b[36m"; // Cyan for static text | |
const varColor = "\x1b[35m"; // Magenta for variables | |
console.log(`${textColor}${projectVersion} in environment ${varColor}${gitEnvironment}${textColor} with tag ${varColor}${dockerTag}${reset}.`); | |
core.setOutput("docker_tag", dockerTag); | |
core.setOutput("git_environment", gitEnvironment); | |
core.setOutput("commit_id", shortSha); | |
core.setOutput("project_version", projectVersion); | |
- name: Get Github last release name | |
id: last_release | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const latestRelease = await github.rest.repos.getLatestRelease({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
}); | |
const reset = "\x1b[0m"; | |
const textColor = "\x1b[36m"; // Cyan for static text | |
const varColor = "\x1b[35m"; // Magenta for variables | |
console.log(`${textColor}The last release is ${varColor}${latestRelease.data.tag_name}${textColor}.${reset}`); | |
core.setOutput("last_release_ref", latestRelease.data.tag_name); | |
- name: Generate Changelog | |
id: changelog | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const lastRelease = '${{ steps.last_release.outputs.last_release_ref }}'; | |
const currentSha = context.sha; | |
const pulls = await github.rest.pulls.list({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
state: 'closed', | |
per_page: 100, | |
}); | |
const mergedPulls = pulls.data.filter(pr => | |
pr.merged_at && | |
pr.merge_commit_sha >= lastRelease && | |
pr.merge_commit_sha <= currentSha | |
); | |
let changes = "## What's Changed\n"; | |
let contributorsNames = new Set(); | |
mergedPulls.forEach(pr => { | |
changes += `* ${pr.title} ${pr.html_url}\n`; | |
contributorsNames.add(pr.user.login); | |
}); | |
let contributors = `### Contributors | |
Thanks to @${Array.from(contributorsNames).join(', @')}.\n`; | |
const fullChangelog = `**Full Changelog**: https://github.com/${context.repo.owner}/${context.repo.repo}/compare/${lastRelease}...${currentSha}`; | |
const changelog = changes + '\n' + (contributorsNames.size ? contributors + '\n' : '') + fullChangelog; | |
const reset = "\x1b[0m"; | |
const textColor = "\x1b[36m"; // Cyan for static text | |
const varColor = "\x1b[35m"; // Magenta for variables | |
console.log(`${textColor}Changelog:${reset}\n${changelog}`); | |
core.setOutput("changelog", changelog); | |
- name: Output Changelog | |
run: echo "${{ steps.changelog.outputs.changelog }}" | |
docker_image_build: | |
name: "Build" | |
needs: ["info"] | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
platform: | |
- linux/amd64 | |
- linux/arm64 | |
steps: | |
- name: Prepare | |
run: | | |
platform=${{ matrix.platform }} | |
echo "platform_pair=${platform//\//-}" >> $GITHUB_OUTPUT | |
id: prepare | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Docker meta | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY_IMAGE }} | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ vars.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Docker image Build | |
id: build | |
uses: docker/build-push-action@v6 | |
with: | |
file: ./.docker/Dockerfile | |
target: executable | |
context: . | |
platforms: ${{ matrix.platform }} | |
labels: ${{ steps.meta.outputs.labels }} | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
provenance: mode=max | |
build-args: | | |
PROJECT_VERSION=${{ needs.info.outputs.project_version }} | |
outputs: | | |
type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true | |
- name: Export image digest | |
run: | | |
echo "Digest: ${{ steps.build.outputs.digest }}" | |
mkdir -p /tmp/digests | |
digest="${{ steps.build.outputs.digest }}" | |
touch "/tmp/digests/${digest#sha256:}" | |
- name: Upload image digest as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: digests-${{ steps.prepare.outputs.platform_pair }} | |
path: /tmp/digests/* | |
if-no-files-found: error | |
retention-days: 1 | |
- name: Export image to tar | |
uses: docker/build-push-action@v6 | |
with: | |
file: ./.docker/Dockerfile | |
target: executable | |
context: . | |
platforms: ${{ matrix.platform }} | |
labels: ${{ steps.meta.outputs.labels }} | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
provenance: mode=max | |
build-args: | | |
PROJECT_VERSION=${{ needs.info.outputs.project_version }} | |
outputs: | | |
type=oci,dest=./pyramid-oci.tar | |
- name: Upload image as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: image-${{ steps.prepare.outputs.platform_pair }} | |
path: ./pyramid-oci.tar | |
if-no-files-found: error | |
retention-days: 1 | |
security_scanner: | |
name: "Security scan" | |
needs: ["docker_image_build"] | |
runs-on: ubuntu-latest | |
strategy: | |
fail-fast: false | |
matrix: | |
platform: | |
- linux/amd64 | |
- linux/arm64 | |
steps: | |
- name: Prepare | |
run: | | |
platform=${{ matrix.platform }} | |
echo "platform_pair=${platform//\//-}" >> $GITHUB_OUTPUT | |
id: prepare | |
- name: Download tests image | |
uses: actions/download-artifact@v4 | |
with: | |
name: image-${{ steps.prepare.outputs.platform_pair }} | |
- name: Untar OCI Image | |
run: | | |
mkdir -p ./pyramid-oci | |
tar -xvf ./pyramid-oci.tar -C ./pyramid-oci | |
- name: Run Trivy vulnerability scanner | |
uses: aquasecurity/[email protected] | |
with: | |
input: './pyramid-oci' | |
format: 'github' | |
output: 'dependency-results.sbom.json' | |
github-pat: '${{ secrets.GITHUB_TOKEN }}' | |
env: | |
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2' | |
TRIVY_JAVA_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-java-db:1' | |
- name: Print Trivy result in humain format | |
uses: aquasecurity/[email protected] | |
with: | |
input: './pyramid-oci' | |
format: 'table' | |
exit-code: '1' | |
# ignore-unfixed: true | |
severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' | |
env: | |
TRIVY_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-db:2' | |
TRIVY_JAVA_DB_REPOSITORY: 'public.ecr.aws/aquasecurity/trivy-java-db:1' | |
- name: Upload trivy report as a Github artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: trivy-sbom-${{ steps.prepare.outputs.platform_pair }}-report | |
path: '${{ github.workspace }}/dependency-results.sbom.json' | |
retention-days: 90 | |
docker_image_test_build: | |
name: "Build Tests" | |
needs: ["info", "docker_image_build"] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Login to DockerHub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ vars.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Docker image Build | |
id: build | |
uses: docker/build-push-action@v6 | |
with: | |
file: ./.docker/Dockerfile | |
target: tests | |
context: . | |
tags: pyramid:tests | |
cache-from: type=gha | |
cache-to: type=gha,mode=max | |
build-args: | | |
PROJECT_VERSION=${{ needs.info.outputs.project_version }}-tests | |
push: false | |
outputs: type=docker | |
- name: Export tests image | |
run: docker save pyramid:tests -o "./pyramid-tests.tar" | |
- name: Upload tests image as artifact | |
uses: actions/upload-artifact@v4 | |
with: | |
name: image-tests | |
path: ./pyramid-tests.tar | |
if-no-files-found: error | |
retention-days: 1 | |
tests_in_docker: | |
name: "Tests" | |
needs: ["docker_image_test_build"] | |
runs-on: ubuntu-latest | |
steps: | |
- name: Download tests image | |
uses: actions/download-artifact@v4 | |
with: | |
name: image-tests | |
- name: Load Docker image | |
run: docker load -i "./pyramid-tests.tar" | |
- name: Run unit tests | |
run: | | |
mkdir -p ./coverage && chmod 777 ./coverage | |
docker run --rm -v ./coverage:/app/coverage -e DEEZER__ARL=${{ secrets.CONFIG_DEEZER_ARL }} -e SPOTIFY__CLIENT_ID=${{ secrets.CONFIG_SPOTIFY_CLIENT_ID }} -e SPOTIFY__CLIENT_SECRET=${{ secrets.CONFIG_SPOTIFY_CLIENT_SECRET }} pyramid:tests | |
- name: Upload coverage reports to Codecov | |
uses: codecov/[email protected] | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
slug: tristiisch/PyRamid | |
files: ./coverage/coverage1.xml | |
fail_ci_if_error: true | |
docker_image_push: | |
name: "Push" | |
runs-on: ubuntu-latest | |
needs: ["info", "docker_image_build", "tests_in_docker"] | |
steps: | |
- name: Download digests | |
uses: actions/download-artifact@v4 | |
with: | |
path: /tmp/digests | |
pattern: digests-* | |
merge-multiple: true | |
- name: Login to DockerHub | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Docker meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY_IMAGE }} | |
tags: | | |
type=raw,value=${{ needs.info.outputs.docker_tag }} | |
type=raw,value=${{ needs.info.outputs.project_version }} | |
- name: Create manifest list and push | |
working-directory: /tmp/digests | |
run: docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) | |
docker_image_push_private: | |
name: "Push Privates" | |
runs-on: ubuntu-latest | |
needs: ["info", "docker_image_build", "tests_in_docker"] | |
steps: | |
- name: Download digests | |
uses: actions/download-artifact@v4 | |
with: | |
path: /tmp/digests | |
pattern: digests-* | |
merge-multiple: true | |
- name: Login to Github Container Registry | |
uses: docker/login-action@v3 | |
with: | |
registry: ${{ vars.DOCKER_REGISTRY_PRIVATE_URL }} | |
username: ${{ github.actor }} | |
password: ${{ secrets.GITHUB_TOKEN }} | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Docker meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY_IMAGE_PRIVATE }} | |
tags: | | |
type=raw,value=${{ needs.info.outputs.docker_tag }} | |
type=raw,value=${{ needs.info.outputs.project_version }} | |
- name: Create manifest list and push | |
working-directory: /tmp/digests | |
run: docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") $(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) | |
docker_swarm_deploy: | |
name: "Deploy" | |
needs: ["info", "docker_image_push"] | |
runs-on: ubuntu-latest | |
environment: ${{ needs.info.outputs.environment }} | |
if: (github.ref_type == 'tag' && needs.info.outputs.docker_tag == 'latest') || (github.ref_type == 'branch' && needs.info.outputs.docker_tag != 'latest') | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Deploy ${{ needs.info.outputs.project_version }} to ${{ needs.info.outputs.environment }} | |
uses: tristiisch/docker-stack-deployment@master | |
with: | |
deployment_mode: docker-swarm | |
remote_docker_host: ${{ secrets.MANAGER_HOST }} | |
remote_docker_username: ${{ secrets.MANAGER_TO_USER }} | |
ssh_private_key: ${{ secrets.MANAGER_TO_SSH_PRIVATE_KEY }} | |
ssh_public_key: ${{ secrets.MANAGER_SSH_PUBLIC_KEY }} | |
stack_file_path: ${{ vars.DOCKER_COMPOSE_FILENAME }} | |
stack_name: ${{ vars.DOCKER_STACK_NAME }} | |
secrets: ${{ vars.DOCKER_COMPOSE_SERVICE}} ${{ vars.DOCKER_STACK_NAME }} DISCORD__TOKEN ${{ secrets.CONFIG_DISCORD_TOKEN }} DEEZER__ARL ${{ secrets.CONFIG_DEEZER_ARL }} SPOTIFY__CLIENT_ID ${{ secrets.CONFIG_SPOTIFY_CLIENT_ID }} SPOTIFY__CLIENT_SECRET ${{ secrets.CONFIG_SPOTIFY_CLIENT_SECRET }} | |
release_publish: | |
name: "Release" | |
needs: ["info", "docker_image_push"] | |
runs-on: ubuntu-latest | |
if: github.ref_type == 'tag' && github.event_name == 'push' && needs.info.outputs.docker_tag == 'latest' | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Update Release v${{ needs.info.outputs.project_version }} | |
run: | | |
set -eu | |
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) | |
cat <<$EOF > ./changelog.txt | |
The latest version of the Discord bot PyRamid#6882 has been successfully deployed. | |
To start using this updated version, please follow the instructions provided at [PyRamid Usage Guide](https://github.com/tristiisch/PyRamid/#usage). | |
${{ needs.info.outputs.changelog }} | |
## Docker | |
This version is now accessible through various Docker images. Each image creation corresponds to a unique snapshot of this version, while updating the image corresponds to using an updated Docker image tag. | |
### Images availables | |
* \`${{ env.REGISTRY_IMAGE }}:${{ needs.info.outputs.docker_tag }}\` | |
* \`${{ env.REGISTRY_IMAGE }}:${{ needs.info.outputs.project_version }}\` | |
$EOF | |
gh release edit "${{ github.ref_name }}" \ | |
--title "Release v${{ needs.info.outputs.project_version }}" \ | |
--draft=false \ | |
--prerelease=false \ | |
--notes-file "./changelog.txt" | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |