diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..e4ea754 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,120 @@ +--- + +name: 'CI' + + +on: + # workflow_call: + # inputs: + # build-branch: # tag / dev + # required: true + # type: string + push: + branches: + # - '*' # matches every branch that doesn't contain a '/' + # - '*/*' # matches every branch containing a single '/' + - '**' # matches every branch + tags: + - '*' + # pull_request: + # # branches: + # # - '**' + # types: + # # - opened + # - synchronize + # # - closed + # # - reopened + + +# 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.pull_request + || + 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 }}" diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml new file mode 100644 index 0000000..986d3c1 --- /dev/null +++ b/.github/workflows/docker.yaml @@ -0,0 +1,837 @@ +--- + +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_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: + + + - 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=https://raw.githubusercontent.com/${{ github.repository }}/development/README.md" \ + --label 'io.artifacthub.package.maintainers=[{"name":"No Fuss Computing","email":"helpdesk@nofusscomputing.com"}]' \ + \ + --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 dockerfile \ + --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: | + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)" + + 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: | + not_empty="$(jq -r '.Results[] | .Vulnerabilities[]' scan-results.json)" + + 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: vulnerability-report + path: vulnerability-report.md + + - name: Upload scan results + if: + (${{ + inputs.DOCKER_SCAN_IMAGE_VULNERABILITY + }}) + uses: actions/upload-artifact@v4 + with: + name: 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: 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: 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/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" +