diff --git a/.github/.gitkeep b/.github/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/workflows/bump.yaml b/.github/workflows/bump.yaml new file mode 100644 index 0000000..a147d37 --- /dev/null +++ b/.github/workflows/bump.yaml @@ -0,0 +1,562 @@ +--- + +name: 'Bump' + + +on: + # workflow_dispatch: + # inputs: + # CZ_PRE_RELEASE: + # default: none + # required: false + # description: Create Pre-Release {alpha,beta,rc,none} + # CZ_INCREMENT: + # default: none + # required: false + # description: Type of increment to conduct {MAJOR,MINOR,PATCH,none} + workflow_call: + inputs: + CZ_PRE_RELEASE: + default: none + required: false + description: Create Pre-Release {alpha,beta,rc,none} + type: string + CZ_INCREMENT: + default: none + required: false + description: Type of increment to conduct {MAJOR,MINOR,PATCH,none} + type: string + secrets: + WORKFLOW_TOKEN: + description: Token used to create the tag (required to trigger 'tag' workflow) + required: true + # push: + # branches: + # - '**' + # tags: + # - '*' + + + +jobs: + + bump: + name: 'Bump Version' + if: github.event.commits[0].author.name != 'nfc-bot' + runs-on: ubuntu-latest + outputs: + # nextStrict: ${{ steps.get_next_version.outputs.nextStrict }} + version-current: ${{ steps.version-current.outputs.value-out }} + version-new: ${{ steps.version-new.outputs.value-out }} + steps: + + + - name: Checkout Code - ${{ github.ref_name }} Branch + if: ${{ github.ref_name == 'master' }} + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + token: ${{ secrets.WORKFLOW_TOKEN }} + ref: development + + + - name: Checkout Code - ${{ github.ref_name }} Branch + if: ${{ github.ref_name != 'master' }} + uses: actions/checkout@v4 + with: + fetch-depth: 0 + fetch-tags: true + token: ${{ secrets.WORKFLOW_TOKEN }} + ref: ${{ github.ref_name }} + + + # - name: Get Next Version + # id: get_next_version + # uses: ietf-tools/semver-action@v1 + # with: + # token: ${{ github.token }} + # branch: ${{ github.ref_name }} + # noVersionBumpBehavior: warn + # noNewCommitBehavior: warn + + # - name: Get next version + # id: get_next_version + # uses: thenativeweb/get-next-version@main + # with: + # prefix: 'v' # optional, defaults to '' + + + # - name: Show the next version + # if: success() || failure() + # run: | + # echo ${{ steps.get_next_version.outputs.current }}; + # echo ${{ steps.get_next_version.outputs.next }}; + # echo ${{ steps.get_next_version.outputs.nextMajor }}; + # echo ${{ steps.get_next_version.outputs.nextStrict }}; + # echo ${{ steps.get_next_version.outputs.nextMajorStrict }}; + # echo ${{ steps.get_next_version.outputs.bump }}; + + + - name: Install Commitizen + shell: bash + run: | + pip install \ + commitizen==3.28.0 + + + - name: Fetch Current Version + id: version-current + run: | + echo "value-out=$(cz version --project)" >> $GITHUB_OUTPUT + + + # - name: Configure git + # shell: bash + # run: | + # git config --global user.email "helpdesk@nofusscomputing.com"; + # git config --global user.name "nfc_bot"; + + + + # - name: Create Release Changelog + # shell: bash + # run: | + # cz changelog --incremental --dry-run --unreleased-version + + - name: Increment version with .cz.yaml + shell: bash + run: | + if [ "${{ inputs.CZ_PRE_RELEASE }}" != 'none' ]; then + + if [ "0${{ inputs.CZ_PRE_RELEASE }}" != '0' ]; then + + echo "[debug] Pre-Release detected: ${{ inputs.CZ_PRE_RELEASE }}"; + + export pre_release="--prerelease ${{ inputs.CZ_PRE_RELEASE }}"; + + fi; + + fi; + + if [ "${{ inputs.CZ_INCREMENT }}" != 'none' ]; then + + if [ "0${{ inputs.CZ_PRE_RELEASE }}" != '0' ]; then + + echo "[debug] Pre-Release detected: ${{ inputs.CZ_INCREMENT }}"; + + export increment="--increment ${{ inputs.CZ_INCREMENT }}"; + + fi; + + fi; + + cz bump \ + --files-only \ + ${pre_release} \ + ${increment} \ + --yes; + + + - name: Fetch Current Version + id: version-new + run: | + echo "value-out=$(cz version --project)" >> $GITHUB_OUTPUT + + + - name: ls + if: ${{ github.ref_name != 'master' }} + shell: bash + run: | + ls -la + + + - name: Update Changelog + # if: ${{ github.ref_name != 'master' }} + shell: bash + run: | + cz changelog --dry-run --incremental --unreleased-version "${{ steps.version-new.outputs.value-out }}" > changelog-release.md + + + - name: Update Changelog + # if: ${{ github.ref_name != 'master' }} + shell: bash + run: | + cz changelog --unreleased-version "${{ steps.version-new.outputs.value-out }}" + + + + + + # - name: Update Changelog - (Master Branch) + # if: ${{ github.ref_name == 'master' }} + # shell: bash + # run: | + # cz changelog --merge-prerelease --unreleased-version ${{ steps.get_next_version.outputs.nextStrict }}" + # cz changelog --dry-run --incremental --unreleased-version "${{ steps.get_next_version.outputs.nextStrict }}" > changelog-release.md + + + + # - name: Update Changelog - (Master Branch) + # # if: ${{ github.ref_name == 'master' }} + # shell: bash + # run: | + # cz changelog --dry-run --incremental --unreleased-version "${{ steps.get_next_version.outputs.nextStrict }}" > changelog-release.md + + + + # - name: Increment version with .cz.yaml + # shell: bash + # run: | + # if [ "${{ inputs.CZ_PRE_RELEASE }}" != 'none' ]; then + + # echo "[debug] Pre-Release detected: ${{ inputs.CZ_PRE_RELEASE }}"; + + # export pre_release="--prerelease ${{ inputs.CZ_PRE_RELEASE }}"; + + # fi; + + # if [ "${{ inputs.CZ_INCREMENT }}" != 'none' ]; then + + # echo "[debug] Pre-Release detected: ${{ inputs.CZ_INCREMENT }}"; + + # export increment="--increment ${{ inputs.CZ_INCREMENT }}"; + + # fi; + + # cz bump \ + # --files-only \ + # ${pre_release} \ + # ${increment} \ + # --yes; + + + # - name: Get previous tag + # if: ${{ steps.get_next_version.outputs.hasNextVersion }} + # id: previousTag + # run: | + # name=$(git --no-pager tag --sort=creatordate --merged ${{ github.ref_name }} | tail -2 | head -1) + # echo "previousTag: $name" + # echo "previousTag=$name" >> $GITHUB_ENV + + + # - name: Create Temp git tag + # if: ${{ steps.get_next_version.outputs.nextStrict }} + # # id: previousTag + # run: | + # git tag ${{ steps.get_next_version.outputs.nextStrict }}; + + + # - name: Update CHANGELOG + # if: ${{ steps.get_next_version.outputs.nextStrict }} + # id: changelog + # uses: requarks/changelog-action@v1 + # with: + # token: ${{ github.token }} + # # tag: ${{ steps.get_next_version.outputs.current }} + # # tag: ${{ github.ref_name }} + # # fromTag: ${{ github.ref_name }} + # fromTag: ${{ steps.get_next_version.outputs.nextStrict }} + # toTag: ${{ steps.get_next_version.outputs.current }} + # writeToFile: true + # changelogFilePath: CHANGELOG.md + # includeRefIssues: true + # includeInvalidCommits: false + # reverseOrder: false + + # - name: Create Temp git tag + # if: ${{ steps.get_next_version.outputs.nextStrict }} + # # id: previousTag + # run: | + # git tag -d ${{ steps.get_next_version.outputs.nextStrict }}; + + + + # - name: Conventional Changelog Action + # id: changelog + # uses: TriPSs/conventional-changelog-action@v5 + # with: + # github-token: ${{ secrets.github_token }} + # # git-message: 'chore(release): {version}' + # # git-user-name: 'Awesome Changelog Action' + # # git-user-email: 'awesome_changelog@github.actions.com' + # preset: 'conventionalcommits' + # tag-prefix: '' + # input-file: CHANGELOG.md + # output-file: 'CHANGELOG.md' + # # release-count: '10000' + # pre-changelog-generation: '' # pre changelog script file + # # version-file: './my_custom_version_file.json' // or .yml, .yaml, .toml, mix.exs + # # version-path: 'path.to.version' + # skip-on-empty: true + # skip-version-file: true + # skip-commit: true + # git-branch: ${{ github.ref_name }} + # skip-bump: true + # git-push: true + # skip-tag: true + # skip-git-pull: true + + + + # - name: Create Release Changelog + # if: ${{ steps.get_next_version.outputs.nextStrict }} + # shell: bash + # run: | + # echo '${{ steps.changelog.outputs.clean_changelog }}' > changelog-release.md + + + - name: Upload Release Changelog + if: ${{ steps.version-new.outputs.value-out }} + uses: actions/upload-artifact@v4 + with: + name: changelog-release + path: changelog-release.md + + + - name: Create Release Changelog + if: ${{ steps.version-new.outputs.value-out }} + shell: bash + run: | + rm changelog-release.md; + git status; + + + - name: Commit the changelog + if: ${{ steps.version-new.outputs.value-out && github.ref_name == 'master' }} + uses: stefanzweifel/git-auto-commit-action@v5 + with: + # Optional. Commit message for the created commit. + # Defaults to "Apply automatic changes" + commit_message: 'build: bump version ${{ steps.version-current.outputs.value-out }} -> ${{ steps.version-new.outputs.value-out }}' + + # Optional. Local and remote branch name where commit is going to be pushed + # to. Defaults to the current branch. + # You might need to set `create_branch: true` if the branch does not exist. + branch: development + + # Optional. Options used by `git-commit`. + # See https://git-scm.com/docs/git-commit#_options + # commit_options: '--no-verify --signoff' + + # Optional glob pattern of files which should be added to the commit + # Defaults to all (.) + # See the `pathspec`-documentation for git + # - https://git-scm.com/docs/git-add#Documentation/git-add.txt-ltpathspecgt82308203 + # - https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec + # file_pattern: '.' + + # Optional. Local file path to the repository. + # Defaults to the root of the repository. + # repository: . + + # Optional commit user and author settings + commit_user_name: nfc-bot # defaults to "github-actions[bot]" + commit_user_email: helpdesk@nofusscomputing.com # defaults to "41898282+github-actions[bot]@users.noreply.github.com" + commit_author: nfc-bot # defaults to "username ", where "username" belongs to the author of the commit that triggered the run + + # Optional. Tag name being created in the local repository and + # pushed to remote repository and defined branch. + tagging_message: ${{ steps.version-new.outputs.value-out }} + + # Optional. Option used by `git-status` to determine if the repository is + # dirty. See https://git-scm.com/docs/git-status#_options + # status_options: '--untracked-files=no' + + # Optional. Options used by `git-add`. + # See https://git-scm.com/docs/git-add#_options + # add_options: '-u' + + # Optional. Options used by `git-push`. + # See https://git-scm.com/docs/git-push#_options + # push_options: '--force' + + # Optional. Disable dirty check and always try to create a commit and push + skip_dirty_check: true + + # Optional. Skip internal call to `git fetch` + skip_fetch: true + + # Optional. Skip internal call to `git checkout` + skip_checkout: true + + # Optional. Prevents the shell from expanding filenames. + # Details: https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html + disable_globbing: true + + # Optional. Create given branch name in local and remote repository. + # create_branch: true + + + - name: Commit the changelog + if: ${{ steps.version-new.outputs.value-out && github.ref_name != 'master'}} + uses: stefanzweifel/git-auto-commit-action@v5 + with: + # Optional. Commit message for the created commit. + # Defaults to "Apply automatic changes" + commit_message: 'build: bump version ${{ steps.version-current.outputs.value-out }} -> ${{ steps.version-new.outputs.value-out }}' + + # Optional. Local and remote branch name where commit is going to be pushed + # to. Defaults to the current branch. + # You might need to set `create_branch: true` if the branch does not exist. + branch: ${{ github.ref_name }} + + # Optional. Options used by `git-commit`. + # See https://git-scm.com/docs/git-commit#_options + # commit_options: '--no-verify --signoff' + + # Optional glob pattern of files which should be added to the commit + # Defaults to all (.) + # See the `pathspec`-documentation for git + # - https://git-scm.com/docs/git-add#Documentation/git-add.txt-ltpathspecgt82308203 + # - https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec + # file_pattern: '.' + + # Optional. Local file path to the repository. + # Defaults to the root of the repository. + # repository: . + + # Optional commit user and author settings + commit_user_name: nfc-bot # defaults to "github-actions[bot]" + commit_user_email: helpdesk@nofusscomputing.com # defaults to "41898282+github-actions[bot]@users.noreply.github.com" + commit_author: nfc-bot # defaults to "username ", where "username" belongs to the author of the commit that triggered the run + + # Optional. Tag name being created in the local repository and + # pushed to remote repository and defined branch. + tagging_message: ${{ steps.version-new.outputs.value-out }} + + # Optional. Option used by `git-status` to determine if the repository is + # dirty. See https://git-scm.com/docs/git-status#_options + # status_options: '--untracked-files=no' + + # Optional. Options used by `git-add`. + # See https://git-scm.com/docs/git-add#_options + # add_options: '-u' + + # Optional. Options used by `git-push`. + # See https://git-scm.com/docs/git-push#_options + # push_options: '--force' + + # Optional. Disable dirty check and always try to create a commit and push + skip_dirty_check: true + + # Optional. Skip internal call to `git fetch` + skip_fetch: true + + # Optional. Skip internal call to `git checkout` + skip_checkout: true + + # Optional. Prevents the shell from expanding filenames. + # Details: https://www.gnu.org/software/bash/manual/html_node/Filename-Expansion.html + disable_globbing: true + + # Optional. Create given branch name in local and remote repository. + # create_branch: true + + + + # - name: Update Changelog + # if: ${{ github.ref_name != 'master' }} + # shell: bash + # run: | + # git tag ${{ steps.get_next_version.outputs.nextStrict }} + + - name: Configure git + shell: bash + run: | + git config --global user.email "helpdesk@nofusscomputing.com"; + git config --global user.name "nfc-bot"; + + - name: Checkout master + if: ${{ github.ref_name == 'master' }} + shell: bash + run: | + git checkout master; + + - name: Merge changes to master + if: ${{ github.ref_name == 'master' }} + shell: bash + run: | + git merge --no-ff development; + + + - name: Push changes + if: ${{ github.ref_name == 'master' }} + shell: bash + run: | + git push origin master; + + + + release: + needs: + - bump + name: Release + if: ${{ needs.bump.outputs.version-new && github.event.commits[0].author.name != 'nfc-bot' }} + runs-on: ubuntu-latest + steps: + + - name: Download Release Changelog + # if: ${{ steps.get_next_version.outputs.nextStrict }} + uses: actions/download-artifact@v4 + with: + name: changelog-release + # path: changelog-release.md + + + - name: Create Draft GH Release - master Branch + if: ${{ inputs.CZ_PRE_RELEASE == 'none' || github.ref_name == 'master' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ needs.bump.outputs.version-new }} + tag_name: ${{ needs.bump.outputs.version-new }} + body_path: changelog-release.md + make_latest: true + prerelease: false + draft: true + + + - name: Create Draft GH Release - Other Branches + if: ${{ inputs.CZ_PRE_RELEASE != 'none' && github.ref_name != 'master' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ needs.bump.outputs.version-new }} + tag_name: ${{ needs.bump.outputs.version-new }} + body_path: changelog-release.md + # make_latest: true + draft: true + prerelease: true + + + release-label: + needs: + - bump + - release + if: ${{ needs.bump.outputs.version-new && github.event.commits[0].author.name != 'nfc-bot'}} + name: Create Release Label + permissions: + contents: read + issues: write + runs-on: ubuntu-latest + steps: + + - run: | + mkdir -p .github; + echo " + labels: + v${{ needs.bump.outputs.version-new }}: + color: "EEE600" + description: Version Affected. + + " > .github/labels.yml; + + cat .github/labels.yml; + + + - uses: oliversalzburg/action-label-manager@v0.0.9 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + + diff --git a/.github/workflows/code-coverage-report.yaml b/.github/workflows/code-coverage-report.yaml new file mode 100644 index 0000000..8fc875c --- /dev/null +++ b/.github/workflows/code-coverage-report.yaml @@ -0,0 +1,93 @@ +--- + +name: 'Process Coverage Artifact' + +on: + workflow_run: + workflows: + - 'Unit Test' + types: + - completed + + +permissions: + contents: read + actions: read + checks: write + + +jobs: + report: + runs-on: ubuntu-latest + # strategy: + # max-parallel: 4 + # matrix: + # python-version: ['3.12'] + name: Coverage + steps: + + - name: Run Tests + run: | + ls -l; + + - name: Download Coverage Artifact + uses: actions/download-artifact@v4 + with: + name: coverage-report-3.12 + # path: coverage.xml + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ github.token }} + + - name: ls + if: success() || failure() + run: | + ls -l; + + - name: Code Coverage Report + uses: irongut/CodeCoverageSummary@v1.3.0 + with: + filename: coverage.xml + badge: true + fail_below_min: true + format: markdown + hide_branch_rate: false + hide_complexity: false + indicators: true + output: both + thresholds: '60 85' + + + # - name: Add Coverage PR Comment + # uses: marocchino/sticky-pull-request-comment@v2 + # if: github.event_name == 'pull_request' + # with: + # recreate: true + # path: code-coverage-results.md + + + - name: ls + if: success() || failure() + run: | + ls -l; + + # - name: Adding markdown + # run: | + # cat $(ls *.md | tail -1) >> $GITHUB_STEP_SUMMARY + + - name: create status check/comment for code coverage results + id: jest_coverage_check + uses: im-open/process-code-coverage-summary@v2.3.0 + with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ github.token }} + summary-file: code-coverage-results.md + create-pr-comment: true + update-comment-if-one-exists: true + update-comment-key: "${{ env.GITHUB-JOB }}_${{ env.GITHUB-ACTION }}" + + - name: Upload Coverage Summary + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: code-coverage-results-3.12 + path: code-coverage-results.md diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..6fcdc67 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,971 @@ +--- + +name: 'Docker' + + +on: + workflow_call: + inputs: + DOCKER_BUILD_REGISTRY: + default: "ghcr.io" + description: Registry where build image will live + required: false + type: string + DOCKER_BUILD_IMAGE_NAME: + default: "${{ github.repository }}" + description: Docker image name for building image + required: false + type: string + DOCKER_BUILD_IMAGE_TAG: + default: "${{ github.sha }}" + description: Docker image tag for building image + required: false + type: string + DOCKER_FILE: + default: "dockerfile" + description: Path to the dockerfile + required: false + type: string + DOCKER_LABEL_ARTIFACTHUB_MAINTAINER: + default: '[{"name":"No Fuss Computing","email":"helpdesk@nofusscomputing.com"}]' + description: Artifact hub Maintainer + required: false + type: string + DOCKER_LABEL_ARTIFACTHUB_README: + default: 'https://raw.githubusercontent.com/${{ github.repository }}/development/README.md' + description: Artifact hub ReadMe + required: false + type: string + DOCKER_PUBLISH_REGISTRY: + default: "docker.io" + description: Registry where image will be published to + required: false + type: string + DOCKER_PUBLISH_IMAGE_NAME: + default: "${{ github.repository }}" + description: Docker image name for publishing the image + required: false + type: string + DOCKER_SCAN_IMAGE_VULNERABILITY: + default: true + description: Scan Image with Trivy + required: false + type: boolean + DOCKER_TAG_IMAGE_TAG_SOURCE: + default: "${{ github.sha }}" + description: Docker image tag Used for source Image to tag + required: false + type: string + DOCKER_TAG_IMAGE_TAG_LATEST: + default: true + description: Create image with tag 'Latest' + required: false + type: boolean + DOCKER_TAG_IMAGE_TAG_SHA: + default: true + description: Create image with tag that is the git commit + required: false + type: boolean + secrets: + DOCKER_PUBLISH_USERNAME: + # default: ${{ github.actor }} + description: Publish Docker registry username + required: true + # type: string + DOCKER_PUBLISH_PASSWORD: + # default: ${{ secrets.GITHUB_TOKEN }} + description: Publish Docker registry username + required: true + # type: string + +permissions: + pull-requests: write + contents: write + actions: read + checks: write + packages: write + security-events: write + statuses: write + id-token: write + attestations: write + +jobs: + + docker-build: + if: + (${{ + github.event.push + || + github.ref_type == 'tag' + }}) + runs-on: ubuntu-latest + name: Build Image + outputs: + build-image-digest: ${{ steps.image-digest.outputs.value-out }} + steps: + + + + - name: Debug + run: | + echo "${{ github.event.pull_request.head.repo.full_name || github.repository }}"; + echo "**************************"; + echo "${{ github.event.pull_request.head.repo.full_name }}"; + echo "**************************"; + echo "${{ github.repository }}"; + echo "**************************"; + echo "${{ github.event.pull_request.head.repo }}"; + echo "**************************"; + echo "${{ github.event.push }}"; + echo "**************************"; + - uses: actions/checkout@v4 + + # - name: Dummy Task + # if: ${{ github.ref_type == 'tag' }} + # run: | + # echo "This Job does nothing however as 'docker-build' is a dependency job, must do something."; + + + + - name: Log into registry ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_BUILD_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Setup BuildX + # if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx create --name project-v3-builder; + docker buildx use project-v3-builder; + + + - name: build image + # if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx build --platform="linux/amd64,linux/arm64" . \ + --label "org.opencontainers.image.created=$(date '+%Y-%m-%dT%H:%M:%S%:z')" \ + --label "org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ + --label "org.opencontainers.image.revision=${{ github.sha }}" \ + \ + --label "io.artifacthub.package.readme-url=${{ inputs.DOCKER_LABEL_ARTIFACTHUB_README }}" \ + --label 'io.artifacthub.package.maintainers=${{ inputs.DOCKER_LABEL_ARTIFACTHUB_MAINTAINER }}' \ + \ + --annotation "org.opencontainers.image.description=a DESCRIPTION for multi-arch images" \ + --annotation "org.opencontainers.image.created=$(date '+%Y-%m-%dT%H:%M:%S%:z')" \ + --annotation "org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ + --annotation "org.opencontainers.image.revision=${{ github.sha }}" \ + --push \ + --file ${{ inputs.DOCKER_FILE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}; + + + - name: Remove "Unknown" Image from Manifest + # if: ${{ github.ref_type != 'tag' }} + run: | + + DOCKER_MULTI_ARCH_IMAGES=$(docker buildx imagetools inspect "${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}" --format "{{ range .Manifest.Manifests }}{{ if ne (print .Platform) \"&{unknown unknown [] }\" }}${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}@{{ println .Digest }}{{end}} {{end}}"); + + docker buildx imagetools create $DOCKER_MULTI_ARCH_IMAGES \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:dev; + + + - name: Fetch image + run: | + docker pull ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} >> /dev/null; + + + - name: Fetch Manifest digest + id: image-digest + run: | + echo "value-out=$(docker inspect --format='{{index .RepoDigests 0}}' ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} | cut -d '@' -f 2)" >> $GITHUB_OUTPUT + + + - name: Attest + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/attest-build-provenance@v1 + id: image-attest + with: + subject-name: ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }} + subject-digest: ${{ steps.image-digest.outputs.value-out }} + push-to-registry: true + + + - name: Upload Image Attestation Artifact + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image + path: ${{ steps.image-attest.outputs.bundle-path }} + + + - name: Cleanup BuildX + # if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx rm project-v3-builder; + + + + docker-scan-vulnerability: + if: + (${{ + ( + github.event.push + || + github.ref_type == 'tag' + ) + && + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + + needs: + - docker-build + runs-on: ubuntu-latest + name: Vulnerability Scan + steps: + - uses: actions/checkout@v4 + + + - name: Dummy Task + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY == false + }}) + run: | + echo "Scanning image turned off.This Job does nothing however as 'docker-scan-vulnerability' is a dependency job, must do something."; + + + - name: Log into registry ${{ inputs.DOCKER_BUILD_REGISTRY }} + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_BUILD_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Run Trivy vulnerability scanner (sarif Report) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: aquasecurity/trivy-action@0.20.0 + with: + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'LOW,MEDIUM,HIGH,CRITICAL' + vuln-type: 'os,library' + scanners: vuln + ignore-unfixed: true + + + # - name: Upload Trivy Vulnerability Scan as a release asset + # if: ${{ github.ref_type == 'tag' }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "trivy-vulnerability-scan.sarif" + # file-path: trivy-results.sarif + + - name: Create Draft GH Release + if: ${{ github.ref_type == 'tag' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + # body_path: changelog-release.md + # make_latest: true + draft: true + files: | + trivy-results.sarif + + + - name: Upload Trivy scan results to GitHub Security tab + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + + - name: Run Trivy vulnerability scanner (json Report) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: aquasecurity/trivy-action@0.20.0 + with: + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + format: 'json' + output: 'scan-results.json' + severity: 'LOW,MEDIUM,HIGH,CRITICAL' + vuln-type: 'os,library' + scanners: vuln + ignore-unfixed: false + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: container-scan-results-json + path: scan-results.json + + + - run: | + ls -la + + - name: Create Vulnerabilities (Critical/High) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + run: | + if [ "$(jq -r '.Results')" ]; then + + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)"; + + else + + not_empty=""; + + fi + + + jq -r ' + [ + "# Image Scan Results", + "", + "**Scan Date:** _" + ( .CreatedAt // "" ) + "_", + "**Image:** _" + ( .ArtifactName // "" ) + "_", + "**OS:** _" + ( .Metadata.OS.Family // "" ) + " " + ( .Metadata.OS.Name // "" ) + "_", + "" + ] | join("\n") + ' scan-results.json > vulnerability-report.md + + if [ "$not_empty" ]; then + jq -r ' + def hr(severity): + if severity == "HIGH" or severity == "CRITICAL" then true else false end; + def to_md: + "| " + (.VulnerabilityID // "") + " | " + (.PkgName // "") + " | " + (.InstalledVersion // "") + " | " + (.Severity // "") + " | " + (.Title // "") + " |"; + [ + "## High and Critical Vulnerabilities", + "", + "| Vulnerability ID | Package | Version | Severity | Description |", + "| --------- | ----- | ----- | ----- | -------|", + (.Results[] | .Vulnerabilities[] | select(hr(.Severity)) | to_md), + "" + ] | join("\n") + ' scan-results.json >> vulnerability-report.md + + else + + echo "**Nothing Found**" >> vulnerability-report.md + + fi; + + + + - name: Create Full Vulnerabilities + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + run: | + if [ "$(jq -r '.Results')" ]; then + + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)"; + + else + + not_empty=""; + + fi + + + jq -r ' + [ + "# Full Image Scan Results", + "", + "**Scan Date:** _" + ( .CreatedAt // "" ) + "_", + "**Image:** _" + ( .ArtifactName // "" ) + "_", + "**OS:** _" + ( .Metadata.OS.Family // "" ) + " " + ( .Metadata.OS.Name // "" ) + "_", + "" + ] | join("\n") + ' scan-results.json > full-vulnerability-report.md + + if [ "$not_empty" ]; then + jq -r ' + def hr(severity): + if severity == "HIGH" or severity == "CRITICAL" then true else false end; + def to_md: + "| " + (.VulnerabilityID // "") + " | " + (.PkgName // "") + " | " + (.InstalledVersion // "") + " | " + (.Severity // "") + " | " + (.Title // "") + " |"; + [ + "## Vulnerabilities", + "", + "| Vulnerability ID | Package | Version | Severity | Description |", + "| --------- | ----- | ----- | ----- | -------|", + (.Results[] | .Vulnerabilities[] | select(.Severity) | to_md), + "" + ] | join("\n") + ' scan-results.json >> full-vulnerability-report.md + + else + + echo "**Nothing Found**" >> full-vulnerability-report.md + + fi; + + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: docker-vulnerability-report + path: vulnerability-report.md + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: docker-vulnerability-report-full + path: full-vulnerability-report.md + + + + docker-sbom: + if: + (${{ + ( + github.event.push + || + github.ref_type == 'tag' + ) + }}) + needs: + - docker-build + runs-on: ubuntu-latest + name: Image SBOM + steps: + + + - name: Scan Image + uses: aquasecurity/trivy-action@0.20.0 + with: + scan-type: image + format: cyclonedx + output: dependency-results.sbom.json + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + scan-ref: . + ignore-unfixed: false + vuln-type: os,library + severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL + list-all-pkgs: false + + + - name: Upload SBOM as a Github artifact + uses: actions/upload-artifact@v4 + with: + name: trivy-sbom-report + path: '${{ github.workspace }}/dependency-results.sbom.json' + + + # - name: Upload Trivy SBOM as a release asset + # if: ${{ github.ref_type == 'tag' }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "dependency-scan.sbom.json" + # file-path: dependency-results.sbom.json + + - name: Create Draft GH Release + if: ${{ github.ref_type == 'tag' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + # body_path: changelog-release.md + # make_latest: true + draft: true + files: | + dependency-results.sbom.json + + - name: Log into registry ${{ inputs.DOCKER_BUILD_REGISTRY }} + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_BUILD_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Generate SBOM Attestation + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + id: sbom-attest + uses: actions/attest-sbom@v1 + with: + subject-name: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}' + subject-digest: ${{ needs.docker-build.outputs.build-image-digest }} + sbom-path: 'dependency-results.sbom.json' + push-to-registry: true + + + - name: Upload SBOM Attestation Artifact + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom + path: ${{ steps.sbom-attest.outputs.bundle-path }} + + + docker-reports: + # if: ${{ + # ( + # github.event.push + # || + # github.ref_type == 'tag' + # ) + # }} + needs: + - docker-scan-vulnerability + - docker-build + runs-on: ubuntu-latest + name: Create Reports + steps: + + + - name: Dummy Task + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY == false + }} + run: | + echo "Scanning image turned off.This Job does nothing however as 'docker-scan-vulnerability' is a dependency job, must do something."; + + + - name: Fetch Scan Results + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }} + uses: actions/download-artifact@v4 + with: + name: docker-vulnerability-report-full + + + - uses: dtinth/markdown-report-action@v1 + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }} + with: + name: Docker Vulnerability Report + title: Vulnerability Report + body-file: full-vulnerability-report.md + + + + docker-tagged: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-scan-vulnerability + - docker-reports + runs-on: ubuntu-latest + name: Tagged Image + steps: + + + - name: Log into registry ${{ inputs.DOCKER_BUILD_REGISTRY }} + if: + (${{ + github.ref_type != 'tag' + }}) + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_BUILD_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Create Image Tag '${{ github.ref_name }}' + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ github.ref_name }}; + + + - name: Create Image Tag 'latest' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_LATEST }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:latest; + + + + docker-pr-comment: + if: ${{ github.ref_type != 'tag' }} + needs: + - docker-scan-vulnerability + runs-on: ubuntu-latest + name: PR Comment (Vulnerability) + steps: + + + - name: Fetch Vulnerability Report + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + uses: actions/download-artifact@v4 + with: + name: docker-vulnerability-report + + + - name: Capture scan results + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + run: | + content=$(cat vulnerability-report.md | head -c 65000) + echo "report<> $GITHUB_ENV + echo "$content" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - uses: jwalton/gh-find-current-pr@v1 + id: finder + + - name: Comment scan results on PR + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + number: ${{ steps.finder.outputs.pr }} + header: Image Scan Results + message: | + ${{ env.report }} + + + + docker-publish: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-build + - docker-scan-vulnerability + - docker-reports + - docker-tagged + runs-on: ubuntu-latest + name: Publish + steps: + + + - name: Log into registry ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + username: ${{ secrets.DOCKER_PUBLISH_USERNAME }} + password: ${{ secrets.DOCKER_PUBLISH_PASSWORD }} + + + - name: Tag Image with GIT Tag '${{ github.ref_name }}' + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} \ + + + + - name: Tag Image with GIT commit '${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }}' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_SHA }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + + + - name: Fetch image ${{ github.ref_name }} + run: | + docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} >> /dev/null; + + + - name: Fetch Manifest digest ${{ github.ref_name }} + id: image-digest + run: | + echo "value-out=$(docker inspect --format='{{index .RepoDigests 0}}' ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} | cut -d '@' -f 2)" >> $GITHUB_OUTPUT + + + - name: Attest ${{ github.ref_name }} + uses: actions/attest-build-provenance@v1 + id: image-attest + with: + subject-name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }} + subject-digest: ${{ steps.image-digest.outputs.value-out }} + push-to-registry: true + + + - name: Upload Image Attestation Artifact ${{ github.ref_name }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-published + path: ${{ steps.image-attest.outputs.bundle-path }} + + + - name: Download SBOM as a Github artifact + uses: actions/download-artifact@v4 + with: + name: trivy-sbom-report + + + - name: Generate SBOM Attestation (publish) + id: sbom-attest + uses: actions/attest-sbom@v1 + with: + subject-name: '${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}' + subject-digest: ${{ needs.docker-build.outputs.build-image-digest }} + sbom-path: 'dependency-results.sbom.json' + push-to-registry: true + + + - name: Upload SBOM Attestation Artifact (publish) + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom-published + path: ${{ steps.sbom-attest.outputs.bundle-path }} + + + + - name: Tag Image with GIT 'latest' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_LATEST }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:latest; + + + - name: Append GH Release Body + if: ${{ github.ref_type == 'tag' }} + id: release + uses: softprops/action-gh-release@v2 + with: + append_body: true + draft: true + body: | + ### Images part of this release + + The following images were built and published: + + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:latest` + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }}` + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }}` + + + + docker-release-files: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-build + - docker-sbom + - docker-tagged + - docker-publish + runs-on: ubuntu-latest + name: Release Files + steps: + + + - name: Fetch Image Attestation Artifact - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-published + path: attestation-image/ + + + - + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + mv attestation-image/attestation.jsonl ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl + + + - name: Fetch SBOM Attestation Artifact - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom-published + path: attestation-sbom/ + + + - if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + mv attestation-sbom/attestation.jsonl ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-sbom.jsonl + + + - if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + ls -la; + + + + # - name: Upload created artifact to release assets - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + # if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl" + # file-path: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl + + - name: Create Draft GH Release + if: ${{ github.ref_type == 'tag' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + # body_path: changelog-release.md + # make_latest: true + draft: true + files: | + ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl + ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-sbom.jsonl + + + # - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + # if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom.jsonl" + # file-path: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-sbom.jsonl + + + - name: Fetch Image Attestation Artifact - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image + path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image/ + + + - run: | + mv ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image/attestation.jsonl ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl + + + - name: Fetch SBOM Attestation Artifact - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom + path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom/ + + + - run: | + mv ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom/attestation.jsonl ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom.jsonl + + + - run: | + ls -la; + + + # - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl" + # file-path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl + + - name: Create Draft GH Release + if: ${{ github.ref_type == 'tag' }} + # id: release + uses: softprops/action-gh-release@v2 + with: + name: ${{ github.ref_name }} + tag_name: ${{ github.ref_name }} + # body_path: changelog-release.md + # make_latest: true + draft: true + files: | + ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl + ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom.jsonl + + + # - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + # uses: mkatanski/release-files-action@v1.1.3 + # with: + # token: ${{ secrets.GITHUB_TOKEN }} + # release-tag: ${{ github.ref_name }} + # name: "${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom.jsonl" + # file-path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom.jsonl + + + # - name: Update Release + # uses: nicovince/manage-release@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # files: + # release: ${{ github.ref_name }} + # tag: ${{ github.ref_name }} + + + docker-release: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-release-files + name: Mark Release Live + runs-on: ubuntu-latest + steps: + + # - name: Mark GH Release as not a draft + # # if: ${{ github.ref_type == 'tag' }} + # id: release + # uses: softprops/action-gh-release@v2 + # with: + # name: ${{ github.ref_name }} + # tag_name: ${{ github.ref_name }} + # # body_path: changelog-release.md + # make_latest: true + # draft: false + + - name: Publish Release + uses: grzegorzkrukowski/action-publish-github-release@v1 + with: + tag_name: ${{ github.ref_name }} + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml new file mode 100644 index 0000000..cd124f5 --- /dev/null +++ b/.github/workflows/pull-requests.yaml @@ -0,0 +1,47 @@ +--- + +name: Pull Requests + + +on: + workflow_call: + + +jobs: + + conventional-pr-title: + name: Conventional PR Title + runs-on: ubuntu-latest + steps: + + + - name: Conventional Commit PR Title + uses: agenthunt/conventional-commit-checker-action@v1.0.0 + with: + pr-title-regex: "^(.+)(?:(([^)s]+)))?: (.+)" + pr-body-regex: "(.*)" + + + conventional-commits: + name: Conventional Commits + runs-on: ubuntu-latest + steps: + + - name: Check Commits + uses: taskmedia/action-conventional-commits@v1.1.17 + with: + token: ${{ github.token }} + skip_merge: true + skip_revert: true + types: "build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test" + + + pr_dependencies: + runs-on: ubuntu-latest + name: Dependency Check + steps: + - uses: gregsdennis/dependencies-action@4fc2a4879387b43f784920699cb9303dd0524ac4 + with: + custom-domains: my-custom-domain.io another.domain.com + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..aa4cbca --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,53 @@ +name: Release + +on: + workflow_call: + + + +jobs: + release: + name: Release + if: ${{ github.ref_type == 'tag' }} + runs-on: ubuntu-latest + steps: + + + - name: Create GH Release + if: ${{ github.ref_type == 'tag' }} + id: release + uses: softprops/action-gh-release@v2 + with: + body: | + # A title block + + Some release text + + A [link](https://nofusscomputing.com) does render as markdown works. + + + release-label: + if: ${{ github.ref_type == 'tag' }} + name: Create Release Label + permissions: + contents: read + issues: write + runs-on: ubuntu-latest + steps: + + - run: | + mkdir -p .github; + echo " + labels: + v${{ github.ref_name }}: + color: "EEE600" + description: Version Affected. + + " > .github/labels.yml; + + cat .github/labels.yml; + + + - uses: oliversalzburg/action-label-manager@v0.0.9 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/temp/ci.yaml b/.github/workflows/temp/ci.yaml new file mode 100644 index 0000000..0f89a22 --- /dev/null +++ b/.github/workflows/temp/ci.yaml @@ -0,0 +1,107 @@ +--- + +name: 'CI' + + +on: + # workflow_call: + # inputs: + # build-branch: # tag / dev + # required: true + # type: string + push: + branches: + - '**' + tags: + - '*' + # pull_request: + # branches: + # - '**' + + +# env: +# DOCKER_BUILD_IMAGE: "ghcr.io/${{ github.repository }}-fred:${{ github.sha }}" + + +# permissions: +# pull-requests: write +# contents: read +# actions: read +# checks: write +# packages: write +# security-events: write +# statuses: write + + + +jobs: + + + docker-changed: + if: + (${{ + github.event.push + || + github.ref_type == 'tag' + }}) + runs-on: ubuntu-latest + name: Docker Changed Check + outputs: + feature: ${{ steps.changes-feature.outputs.src }} + development: ${{ steps.changes-development.outputs.src }} + steps: + + + - uses: actions/checkout@v4 + + + - uses: dorny/paths-filter@v3 + name: Development Changes + if: + ( + github.ref_name == 'development' + ) + id: changes-development + with: + ref: master + filters: | + src: + - '.github/workflows/docker.yaml' + - uses: dorny/paths-filter@v3 + name: Feature Branch + if: + ( + github.ref_name != 'development' + && + github.ref_name != 'master' + ) + id: changes-feature + with: + ref: development + filters: | + src: + - '.github/workflows/docker.yaml' + + + docker-check: + needs: docker-changed + name: 'Docker' + if: + ( + needs.docker-changed.outputs.feature == 'true' + || + needs.docker-changed.outputs.development == 'true' + ) + uses: ./.github/workflows/docker.yaml + with: + DOCKER_BUILD_IMAGE_NAME: "nofusscomputing/workflow-docker" + DOCKER_PUBLISH_IMAGE_NAME: "nofusscomputing/workflow-docker-publish" + DOCKER_PUBLISH_REGISTRY: "ghcr.io" + + + + # release: + # name: 'Release' + # uses: nofusscomputing/scratchpad/.github/workflows/release.yaml@further-testing + # # with: + # # DOCKER_BUILD_IMAGE_NAME: "${{ github.repository }}" \ No newline at end of file diff --git a/.github/workflows/temp/docker.yaml b/.github/workflows/temp/docker.yaml new file mode 100644 index 0000000..fbe1bfd --- /dev/null +++ b/.github/workflows/temp/docker.yaml @@ -0,0 +1,883 @@ +--- + +name: 'Docker' + + +on: + workflow_call: + inputs: + DOCKER_BUILD_REGISTRY: + default: "ghcr.io" + description: Registry where build image will live + required: false + type: string + DOCKER_BUILD_IMAGE_NAME: + default: "${{ github.repository }}" + description: Docker image name for building image + required: false + type: string + DOCKER_BUILD_IMAGE_TAG: + default: "${{ github.sha }}" + description: Docker image tag for building image + required: false + type: string + DOCKER_FILE: + default: "dockerfile" + description: Path to the dockerfile + required: false + type: string + DOCKER_LABEL_ARTIFACTHUB_MAINTAINER: + default: '[{"name":"No Fuss Computing","email":"helpdesk@nofusscomputing.com"}]' + description: Artifact hub Maintainer + required: false + type: string + DOCKER_LABEL_ARTIFACTHUB_README: + default: 'https://raw.githubusercontent.com/${{ github.repository }}/development/README.md' + description: Artifact hub ReadMe + required: false + type: string + DOCKER_PUBLISH_REGISTRY: + default: "docker.io" + description: Registry where image will be published to + required: false + type: string + DOCKER_PUBLISH_IMAGE_NAME: + default: "${{ github.repository }}" + description: Docker image name for publishing the image + required: false + type: string + DOCKER_SCAN_IMAGE_VULNERABILITY: + default: true + description: Scan Image with Trivy + required: false + type: boolean + DOCKER_TAG_IMAGE_TAG_SOURCE: + default: "${{ github.sha }}" + description: Docker image tag Used for source Image to tag + required: false + type: string + DOCKER_TAG_IMAGE_TAG_LATEST: + default: true + description: Create image with tag 'Latest' + required: false + type: boolean + DOCKER_TAG_IMAGE_TAG_SHA: + default: true + description: Create image with tag that is the git commit + required: false + type: boolean + + +permissions: + pull-requests: write + contents: write + actions: read + checks: write + packages: write + security-events: write + statuses: write + id-token: write + attestations: write + +jobs: + + docker-build: + if: + (${{ + github.event.push + || + github.ref_type == 'tag' + }}) + runs-on: ubuntu-latest + name: Build Image + outputs: + build-image-digest: ${{ steps.image-digest.outputs.value-out }} + steps: + + + + - name: Debug + run: | + echo "${{ github.event.pull_request.head.repo.full_name || github.repository }}"; + echo "**************************"; + echo "${{ github.event.pull_request.head.repo.full_name }}"; + echo "**************************"; + echo "${{ github.repository }}"; + echo "**************************"; + echo "${{ github.event.pull_request.head.repo }}"; + echo "**************************"; + echo "${{ github.event.push }}"; + echo "**************************"; + - uses: actions/checkout@v4 + + - name: Dummy Task + if: ${{ github.ref_type == 'tag' }} + run: | + echo "This Job does nothing however as 'docker-build' is a dependency job, must do something."; + + + + - name: Log into registry ghcr.io + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Setup BuildX + if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx create --name project-v3-builder; + docker buildx use project-v3-builder; + + + - name: build image + if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx build --platform="linux/amd64,linux/arm64" . \ + --label "org.opencontainers.image.created=$(date '+%Y-%m-%dT%H:%M:%S%:z')" \ + --label "org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ + --label "org.opencontainers.image.revision=${{ github.sha }}" \ + \ + --label "io.artifacthub.package.readme-url=${{ inputs.DOCKER_LABEL_ARTIFACTHUB_README }}" \ + --label 'io.artifacthub.package.maintainers=${{ inputs.DOCKER_LABEL_ARTIFACTHUB_MAINTAINER }}' \ + \ + --annotation "org.opencontainers.image.description=a DESCRIPTION for multi-arch images" \ + --annotation "org.opencontainers.image.created=$(date '+%Y-%m-%dT%H:%M:%S%:z')" \ + --annotation "org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ + --annotation "org.opencontainers.image.revision=${{ github.sha }}" \ + --push \ + --file ${{ inputs.DOCKER_FILE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}; + + + - name: Remove "Unknown" Image from Manifest + if: ${{ github.ref_type != 'tag' }} + run: | + + DOCKER_MULTI_ARCH_IMAGES=$(docker buildx imagetools inspect "${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}" --format "{{ range .Manifest.Manifests }}{{ if ne (print .Platform) \"&{unknown unknown [] }\" }}${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}@{{ println .Digest }}{{end}} {{end}}"); + + docker buildx imagetools create $DOCKER_MULTI_ARCH_IMAGES \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:dev; + + + - name: Fetch image + run: | + docker pull ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} >> /dev/null; + + + - name: Fetch Manifest digest + id: image-digest + run: | + echo "value-out=$(docker inspect --format='{{index .RepoDigests 0}}' ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }} | cut -d '@' -f 2)" >> $GITHUB_OUTPUT + + + - name: Attest + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/attest-build-provenance@v1 + id: image-attest + with: + subject-name: ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }} + subject-digest: ${{ steps.image-digest.outputs.value-out }} + push-to-registry: true + + + - name: Upload Image Attestation Artifact + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image + path: ${{ steps.image-attest.outputs.bundle-path }} + + + - name: Cleanup BuildX + if: ${{ github.ref_type != 'tag' }} + run: | + docker buildx rm project-v3-builder; + + + + docker-scan-vulnerability: + if: + (${{ + ( + github.event.push + || + github.ref_type == 'tag' + ) + && + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + + needs: + - docker-build + runs-on: ubuntu-latest + name: Vulnerability Scan + steps: + - uses: actions/checkout@v4 + + + - name: Dummy Task + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY == false + }}) + run: | + echo "Scanning image turned off.This Job does nothing however as 'docker-scan-vulnerability' is a dependency job, must do something."; + + + - name: Log into registry ghcr.io + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Run Trivy vulnerability scanner (sarif Report) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: aquasecurity/trivy-action@0.20.0 + with: + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'LOW,MEDIUM,HIGH,CRITICAL' + vuln-type: 'os,library' + scanners: vuln + ignore-unfixed: true + + + - name: Upload Trivy Vulnerability Scan as a release asset + if: ${{ github.ref_type == 'tag' }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "trivy-vulnerability-scan.sarif" + file-path: trivy-results.sarif + + + - name: Upload Trivy scan results to GitHub Security tab + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: 'trivy-results.sarif' + + + - name: Run Trivy vulnerability scanner (json Report) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: aquasecurity/trivy-action@0.20.0 + with: + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + format: 'json' + output: 'scan-results.json' + severity: 'LOW,MEDIUM,HIGH,CRITICAL' + vuln-type: 'os,library' + scanners: vuln + ignore-unfixed: false + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: container-scan-results-json + path: scan-results.json + + + - run: | + ls -la + + - name: Create Vulnerabilities (Critical/High) + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + run: | + if [ "$(jq -r '.Results')" ]; then + + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)"; + + else + + not_empty=""; + + fi + + + jq -r ' + [ + "# Image Scan Results", + "", + "**Scan Date:** _" + ( .CreatedAt // "" ) + "_", + "**Image:** _" + ( .ArtifactName // "" ) + "_", + "**OS:** _" + ( .Metadata.OS.Family // "" ) + " " + ( .Metadata.OS.Name // "" ) + "_", + "" + ] | join("\n") + ' scan-results.json > vulnerability-report.md + + if [ "$not_empty" ]; then + jq -r ' + def hr(severity): + if severity == "HIGH" or severity == "CRITICAL" then true else false end; + def to_md: + "| " + (.VulnerabilityID // "") + " | " + (.PkgName // "") + " | " + (.InstalledVersion // "") + " | " + (.Severity // "") + " | " + (.Title // "") + " |"; + [ + "## High and Critical Vulnerabilities", + "", + "| Vulnerability ID | Package | Version | Severity | Description |", + "| --------- | ----- | ----- | ----- | -------|", + (.Results[] | .Vulnerabilities[] | select(hr(.Severity)) | to_md), + "" + ] | join("\n") + ' scan-results.json >> vulnerability-report.md + + else + + echo "**Nothing Found**" >> vulnerability-report.md + + fi; + + + + - name: Create Full Vulnerabilities + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + run: | + if [ "$(jq -r '.Results')" ]; then + + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)"; + + else + + not_empty=""; + + fi + + + jq -r ' + [ + "# Full Image Scan Results", + "", + "**Scan Date:** _" + ( .CreatedAt // "" ) + "_", + "**Image:** _" + ( .ArtifactName // "" ) + "_", + "**OS:** _" + ( .Metadata.OS.Family // "" ) + " " + ( .Metadata.OS.Name // "" ) + "_", + "" + ] | join("\n") + ' scan-results.json > full-vulnerability-report.md + + if [ "$not_empty" ]; then + jq -r ' + def hr(severity): + if severity == "HIGH" or severity == "CRITICAL" then true else false end; + def to_md: + "| " + (.VulnerabilityID // "") + " | " + (.PkgName // "") + " | " + (.InstalledVersion // "") + " | " + (.Severity // "") + " | " + (.Title // "") + " |"; + [ + "## Vulnerabilities", + "", + "| Vulnerability ID | Package | Version | Severity | Description |", + "| --------- | ----- | ----- | ----- | -------|", + (.Results[] | .Vulnerabilities[] | select(.Severity) | to_md), + "" + ] | join("\n") + ' scan-results.json >> full-vulnerability-report.md + + else + + echo "**Nothing Found**" >> full-vulnerability-report.md + + fi; + + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: docker-vulnerability-report + path: vulnerability-report.md + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: docker-vulnerability-report-full + path: full-vulnerability-report.md + + + + docker-sbom: + if: + (${{ + ( + github.event.push + || + github.ref_type == 'tag' + ) + }}) + needs: + - docker-build + runs-on: ubuntu-latest + name: Image SBOM + steps: + + + - name: Scan Image + uses: aquasecurity/trivy-action@0.20.0 + with: + scan-type: image + format: cyclonedx + output: dependency-results.sbom.json + image-ref: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_BUILD_IMAGE_TAG }}' + scan-ref: . + ignore-unfixed: false + vuln-type: os,library + severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL + list-all-pkgs: false + + + - name: Upload SBOM as a Github artifact + uses: actions/upload-artifact@v4 + with: + name: trivy-sbom-report + path: '${{ github.workspace }}/dependency-results.sbom.json' + + + - name: Upload Trivy SBOM as a release asset + if: ${{ github.ref_type == 'tag' }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "dependency-scan.sbom.json" + file-path: dependency-results.sbom.json + + + - name: Log into registry ghcr.io + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Generate SBOM Attestation + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + id: sbom-attest + uses: actions/attest-sbom@v1 + with: + subject-name: '${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}' + subject-digest: ${{ needs.docker-build.outputs.build-image-digest }} + sbom-path: 'dependency-results.sbom.json' + push-to-registry: true + + + - name: Upload SBOM Attestation Artifact + if: ${{ + github.ref_name == 'development' + || + github.ref_name == 'master' + || + github.ref_type == 'tag' + }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom + path: ${{ steps.sbom-attest.outputs.bundle-path }} + + + docker-reports: + # if: ${{ + # ( + # github.event.push + # || + # github.ref_type == 'tag' + # ) + # }} + needs: + - docker-scan-vulnerability + - docker-build + runs-on: ubuntu-latest + name: Create Reports + steps: + + + - name: Dummy Task + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY == false + }} + run: | + echo "Scanning image turned off.This Job does nothing however as 'docker-scan-vulnerability' is a dependency job, must do something."; + + + - name: Fetch Scan Results + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }} + uses: actions/download-artifact@v4 + with: + name: docker-vulnerability-report-full + + + - uses: dtinth/markdown-report-action@v1 + if: ${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }} + with: + name: Docker Vulnerability Report + title: Vulnerability Report + body-file: full-vulnerability-report.md + + + + docker-tagged: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-scan-vulnerability + - docker-reports + runs-on: ubuntu-latest + name: Tagged Image + steps: + + + - name: Log into registry ghcr.io + if: + (${{ + github.ref_type != 'tag' + }}) + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Create Image Tag '${{ github.ref_name }}' + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ github.ref_name }}; + + + - name: Create Image Tag 'latest' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_LATEST }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:latest; + + + + docker-pr-comment: + if: ${{ github.ref_type != 'tag' }} + needs: + - docker-scan-vulnerability + runs-on: ubuntu-latest + name: PR Comment (Vulnerability) + steps: + + + - name: Fetch Vulnerability Report + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + uses: actions/download-artifact@v4 + with: + name: docker-vulnerability-report + + + - name: Capture scan results + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + run: | + content=$(cat vulnerability-report.md | head -c 65000) + echo "report<> $GITHUB_ENV + echo "$content" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - uses: jwalton/gh-find-current-pr@v1 + id: finder + + - name: Comment scan results on PR + if: ${{ inputs.DOCKER_SCAN_IMAGE_VULNERABILITY }} + uses: marocchino/sticky-pull-request-comment@v2 + with: + number: ${{ steps.finder.outputs.pr }} + header: Image Scan Results + message: | + ${{ env.report }} + + + + docker-publish: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-build + - docker-scan-vulnerability + - docker-reports + - docker-tagged + runs-on: ubuntu-latest + name: Publish + steps: + + + - name: Log into registry ghcr.io + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + + - name: Tag Image with GIT Tag '${{ github.ref_name }}' + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} \ + + + + - name: Tag Image with GIT commit '${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }}' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_SHA }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + + + - name: Fetch image ${{ github.ref_name }} + run: | + docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} >> /dev/null; + + + - name: Fetch Manifest digest ${{ github.ref_name }} + id: image-digest + run: | + echo "value-out=$(docker inspect --format='{{index .RepoDigests 0}}' ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }} | cut -d '@' -f 2)" >> $GITHUB_OUTPUT + + + - name: Attest ${{ github.ref_name }} + uses: actions/attest-build-provenance@v1 + id: image-attest + with: + subject-name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }} + subject-digest: ${{ steps.image-digest.outputs.value-out }} + push-to-registry: true + + + - name: Upload Image Attestation Artifact ${{ github.ref_name }} + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-published + path: ${{ steps.image-attest.outputs.bundle-path }} + + + - name: Download SBOM as a Github artifact + uses: actions/download-artifact@v4 + with: + name: trivy-sbom-report + + + - name: Generate SBOM Attestation (publish) + id: sbom-attest + uses: actions/attest-sbom@v1 + with: + subject-name: '${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}' + subject-digest: ${{ needs.docker-build.outputs.build-image-digest }} + sbom-path: 'dependency-results.sbom.json' + push-to-registry: true + + + - name: Upload SBOM Attestation Artifact (publish) + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom-published + path: ${{ steps.sbom-attest.outputs.bundle-path }} + + + + - name: Tag Image with GIT 'latest' + if: ${{ inputs.DOCKER_TAG_IMAGE_TAG_LATEST }} + run: | + docker buildx imagetools create ${{ inputs.DOCKER_BUILD_REGISTRY }}/${{ inputs.DOCKER_BUILD_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }} \ + --tag ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:latest; + + + - name: Append GH Release Body + if: ${{ github.ref_type == 'tag' }} + id: release + uses: softprops/action-gh-release@v2 + with: + append_body: true + body: | + ## Images + + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:latest` + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ inputs.DOCKER_TAG_IMAGE_TAG_SOURCE }}` + - `docker pull ${{ inputs.DOCKER_PUBLISH_REGISTRY }}/${{ inputs.DOCKER_PUBLISH_IMAGE_NAME }}:${{ github.ref_name }}` + + [another link](https://nofusscomputing.com) does render as markdown works. + + + + docker-release-files: + if: ${{ github.ref_type == 'tag' }} + needs: + - docker-build + - docker-sbom + - docker-tagged + - docker-publish + runs-on: ubuntu-latest + name: Release Files + steps: + + + - name: Fetch Image Attestation Artifact - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-published + path: attestation-image/ + + + - + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + mv attestation-image/attestation.jsonl ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl + + + - name: Fetch SBOM Attestation Artifact - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom-published + path: attestation-sbom/ + + + - if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + mv attestation-sbom/attestation.jsonl ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-sbom.jsonl + + + - if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + run: | + ls -la; + + + + - name: Upload created artifact to release assets - ${{ inputs.DOCKER_PUBLISH_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl" + file-path: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image.jsonl + + + + - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + if: ${{ inputs.DOCKER_PUBLISH_REGISTRY != inputs.DOCKER_BUILD_REGISTRY }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-image-sbom.jsonl" + file-path: ${{ inputs.DOCKER_PUBLISH_REGISTRY }}-attestation-sbom.jsonl + + + - name: Fetch Image Attestation Artifact - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image + path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image/ + + + - run: | + mv ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image/attestation.jsonl ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl + + + - name: Fetch SBOM Attestation Artifact - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom + path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom/ + + + - run: | + mv ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom/attestation.jsonl ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom.jsonl + + + - run: | + ls -la; + + + - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl" + file-path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image.jsonl + + + + - name: Upload created artifact to release assets - ${{ inputs.DOCKER_BUILD_REGISTRY }} + uses: mkatanski/release-files-action@v1.1.3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + release-tag: ${{ github.ref_name }} + name: "${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-image-sbom.jsonl" + file-path: ${{ inputs.DOCKER_BUILD_REGISTRY }}-attestation-sbom.jsonl + + + # - name: Update Release + # uses: nicovince/manage-release@v1 + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # with: + # files: + # release: ${{ github.ref_name }} + # tag: ${{ github.ref_name }} diff --git a/.github/workflows/temp/management.yaml b/.github/workflows/temp/management.yaml new file mode 100644 index 0000000..f5e0ebd --- /dev/null +++ b/.github/workflows/temp/management.yaml @@ -0,0 +1,34 @@ +--- + +name: Management + + +on: + push: + branches: + - '**' + paths: + - .github/labels.yml + workflow_dispatch: + workflow_call: + + +concurrency: manage-labels + + +jobs: + manage-labels: + name: Manage Labels + permissions: + contents: read + issues: write + runs-on: ubuntu-latest + steps: + + + - uses: actions/checkout@v4 + + + - uses: oliversalzburg/action-label-manager@v0.0.9 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/temp/pr.yaml b/.github/workflows/temp/pr.yaml new file mode 100644 index 0000000..59f74ff --- /dev/null +++ b/.github/workflows/temp/pr.yaml @@ -0,0 +1,24 @@ +--- + +name: PR + + +on: + pull_request: {} + workflow_call: + + +jobs: + conventional: + name: Conventional PR Title + runs-on: ubuntu-latest + steps: + + + - name: check-for-cc + # if: ${{ github.event.pull_request }} + id: check-for-cc + uses: agenthunt/conventional-commit-checker-action@v1.0.0 + with: + pr-title-regex: "^(.+)(?:(([^)s]+)))?: (.+)" + pr-body-regex: "(.*)" diff --git a/.github/workflows/temp/release.yaml b/.github/workflows/temp/release.yaml new file mode 100644 index 0000000..aa4cbca --- /dev/null +++ b/.github/workflows/temp/release.yaml @@ -0,0 +1,53 @@ +name: Release + +on: + workflow_call: + + + +jobs: + release: + name: Release + if: ${{ github.ref_type == 'tag' }} + runs-on: ubuntu-latest + steps: + + + - name: Create GH Release + if: ${{ github.ref_type == 'tag' }} + id: release + uses: softprops/action-gh-release@v2 + with: + body: | + # A title block + + Some release text + + A [link](https://nofusscomputing.com) does render as markdown works. + + + release-label: + if: ${{ github.ref_type == 'tag' }} + name: Create Release Label + permissions: + contents: read + issues: write + runs-on: ubuntu-latest + steps: + + - run: | + mkdir -p .github; + echo " + labels: + v${{ github.ref_name }}: + color: "EEE600" + description: Version Affected. + + " > .github/labels.yml; + + cat .github/labels.yml; + + + - uses: oliversalzburg/action-label-manager@v0.0.9 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/unit-test-report.yaml b/.github/workflows/unit-test-report.yaml new file mode 100644 index 0000000..4d9a84b --- /dev/null +++ b/.github/workflows/unit-test-report.yaml @@ -0,0 +1,58 @@ +--- + +name: 'Process Unit Test Artifact' + +on: + workflow_run: + workflows: + - 'Unit Test' + types: + - completed + + +permissions: + contents: read + actions: read + checks: write + + +jobs: + report: + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.10', '3.11', '3.12'] + steps: + + - name: Test Report + if: success() || failure() + uses: dorny/test-reporter@v1 + id: test-report + with: + artifact: unit-test-results-${{ matrix.python-version }} + badge-title: 'Unit Tests [Python ${{ matrix.python-version }}]' + name: Unit Test Report [Python ${{ matrix.python-version }}] + path: '*.xml' + reporter: java-junit + + + - name: Create Shields.io Endpoint.json + if: success() || failure() + run: | + echo " + { + "schemaVersion": 1, + "label": "Unit Test", + "message": "${{ steps.test-report.outputs.passed }} passed | ${{ steps.test-report.outputs.skipped }} skipped", + "namedLogo": "github", + "color": "#000" + }" > endpoint_${{ matrix.python-version }}.json + + + - name: Upload Badge Endpoint json + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: unit-test-shield-endpoint-${{ matrix.python-version }} + path: endpoint_${{ matrix.python-version }}.json diff --git a/.github/workflows/unit-test.yaml b/.github/workflows/unit-test.yaml new file mode 100644 index 0000000..04df40d --- /dev/null +++ b/.github/workflows/unit-test.yaml @@ -0,0 +1,262 @@ +name: 'Unit Test' + +on: + workflow_call: + # push: + # branches: + # - "development" + # tags: + # - '*' + # pull_request: + # branches: + # - "development" + + +jobs: + unit-test: + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.10', '3.11', '3.12'] + + steps: + + + - uses: actions/checkout@v4 + + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements_test.txt + + + - name: Run Tests + shell: bash + run: | + cd app; + pytest --cov --cov-report term --cov-report xml:../coverage.xml --cov-report html:../coverage/ --junit-xml=../unit.JUnit.xml **/tests/unit; + + + - name: Upload Test Report + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: unit-test-results-${{ matrix.python-version }} + path: unit.JUnit.xml + + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: coverage-report-${{ matrix.python-version }} + path: coverage.xml + + + - name: Upload Coverage + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: coverage-${{ matrix.python-version }} + path: coverage/* + + + # should only run on dev/master and tag + report: + needs: + - unit-test + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.10', '3.11', '3.12'] + steps: + + + - name: Test Report + if: success() || failure() + uses: dorny/test-reporter@v1 + id: test-report + with: + artifact: unit-test-results-${{ matrix.python-version }} + # badge-title: 'Unit Tests [Python ${{ matrix.python-version }}]' + name: Unit Test Report [Python ${{ matrix.python-version }}] + path: '*.xml' + reporter: java-junit + + + - name: Create Shields.io Endpoint.json + if: success() || failure() + shell: bash + run: | + echo ' + { + "schemaVersion": 1, + "label": "Unit Test", + "message": "${{ steps.test-report.outputs.passed }} passed | ${{ steps.test-report.outputs.skipped }} skipped", + "namedLogo": "github", + "color": "#000" + }' > endpoint_${{ matrix.python-version }}.json + + + - name: Upload Badge Endpoint json + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: unit-test-shield-endpoint-${{ matrix.python-version }} + path: endpoint_${{ matrix.python-version }}.json + + + + coverage-report: + needs: + - unit-test + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: ['3.12'] + name: Coverage + steps: + + - name: Run Tests + shell: bash + run: | + ls -l; + + - name: Download Coverage Artifact + uses: actions/download-artifact@v4 + with: + name: coverage-report-${{ matrix.python-version }} + # path: coverage.xml + # run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ github.token }} + + - name: ls + shell: bash + if: success() || failure() + run: | + ls -l; + + - name: Code Coverage Report + uses: irongut/CodeCoverageSummary@v1.3.0 + with: + filename: coverage.xml + badge: true + fail_below_min: true + format: markdown + hide_branch_rate: false + hide_complexity: false + indicators: true + output: both + thresholds: '60 85' + + + # - name: Add Coverage PR Comment + # uses: marocchino/sticky-pull-request-comment@v2 + # if: github.event_name == 'pull_request' + # with: + # recreate: true + # path: code-coverage-results.md + + + - name: ls + shell: bash + if: success() || failure() + run: | + ls -l; + + # - name: Adding markdown + # run: | + # cat $(ls *.md | tail -1) >> $GITHUB_STEP_SUMMARY + + - name: create status check/comment for code coverage results + id: jest_coverage_check + uses: im-open/process-code-coverage-summary@v2.3.0 + with: + # github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ github.token }} + summary-file: code-coverage-results.md + create-pr-comment: true + update-comment-if-one-exists: true + update-comment-key: "${{ env.GITHUB-JOB }}_${{ env.GITHUB-ACTION }}" + + - name: Upload Coverage Summary + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + name: code-coverage-results-${{ matrix.python-version }} + path: code-coverage-results.md + + + + + + + # coverage: + # needs: + # - test + # runs-on: ubuntu-latest + # # strategy: + # # max-parallel: 4 + # # matrix: + # # python-version: ['3.12'] + # name: Coverage + # steps: + + # # - name: Run Tests + # # run: | + # # ls -l; + + # - name: Download Coverage Artifact + # uses: actions/download-artifact@v4 + # with: + # name: coverage-report-3.12 + # # path: coverage.xml + # # run-id: ${{ github.event.workflow_run.id }} + # # github-token: ${{ github.token }} + + + # - name: Add Coverage PR Comment + # uses: marocchino/sticky-pull-request-comment@v2 + # if: github.event_name == 'pull_request' + # with: + # recreate: true + # path: code-coverage-results.md + + + # - name: ls + # if: success() || failure() + # run: | + # ls -l; + + # - name: Code Coverage Report + # uses: irongut/CodeCoverageSummary@v1.3.0 + # with: + # filename: coverage.xml + # badge: true + # fail_below_min: true + # format: markdown + # hide_branch_rate: false + # hide_complexity: false + # indicators: true + # output: both + # thresholds: '60 85' + + # - name: ls + # if: success() || failure() + # run: | + # ls -l; + + # - name: Summary + # run: | + # cat $(ls *.md | tail -1) >> $GITHUB_STEP_SUMMARY diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..db61340 --- /dev/null +++ b/dockerfile @@ -0,0 +1,15 @@ +# +# This dockerfile is used for testing the docker workflow +# + +FROM debian:bookworm-slim + + + +LABEL \ + org.opencontainers.image.title="Test" \ + org.opencontainers.image.description="a testing docker container" \ + org.opencontainers.image.documentation="https://nofusscomputing.com" \ + org.opencontainers.image.vendor="No Fuss Computing" \ + io.artifacthub.package.license="MIT" +