workflow #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | ||
| on: | ||
| release: | ||
| types: [published] | ||
| workflow_dispatch: | ||
| concurrency: | ||
| group: release-${{ github.ref }} | ||
| cancel-in-progress: true | ||
| permissions: | ||
| contents: read | ||
| actions: read | ||
| security-events: write | ||
| jobs: | ||
| build-release: | ||
| name: Build & Push image | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| DOCKER_USER: ${{ secrets.DOCKER_USER }} | ||
| DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} | ||
| steps: | ||
| - name: Log workflow context | ||
| run: | | ||
| set -euo pipefail | ||
| echo "::notice::INFO: workflow=release repo=${GITHUB_REPOSITORY} ref=${GITHUB_REF_NAME} actor=${GITHUB_ACTOR}" | ||
| - name: Validate Docker secrets | ||
| run: | | ||
| set -euo pipefail | ||
| if [ -z "${DOCKER_USER:-}" ]; then | ||
| echo "::error::FATAL: DOCKER_USER secret is missing." | ||
| exit 1 | ||
| fi | ||
| if [ -z "${DOCKER_TOKEN:-}" ]; then | ||
| echo "::error::FATAL: DOCKER_TOKEN secret is missing." | ||
| exit 1 | ||
| fi | ||
| echo "::notice::SUCCESS: Docker secrets are present." | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 # tags needed for baseline compare | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
| - name: Docker Hub login | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| username: ${{ env.DOCKER_USER }} | ||
| password: ${{ env.DOCKER_TOKEN }} | ||
| - name: Prepare build context | ||
| run: | | ||
| set -euo pipefail | ||
| echo "::notice::INFO: Preparing Docker build context." | ||
| rm -rf ./image_context | ||
| mkdir -p ./image_context | ||
| cp -a Dockerfile ./image_context/Dockerfile | ||
| cp -a server_manager ./image_context/ | ||
| echo "::notice::SUCCESS: Build context prepared." | ||
| - name: Build and load (no push yet) | ||
| uses: docker/build-push-action@v6 | ||
| with: | ||
| context: ./image_context | ||
| file: ./image_context/Dockerfile | ||
| platforms: linux/amd64 | ||
| tags: | | ||
| ${{ env.DOCKER_USER }}/enshrouded_server_docker:latest | ||
| ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| push: false | ||
| load: true | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max | ||
| - name: Determine previous tag (baseline) | ||
| id: base | ||
| env: | ||
| CURRENT_TAG: ${{ github.event.release.tag_name }} | ||
| run: | | ||
| set -euo pipefail | ||
| PREV=$(git tag --sort=-creatordate | grep -v "^${CURRENT_TAG}$" | head -n1 || true) | ||
| if [ -n "$PREV" ]; then | ||
| echo "base_tag=$PREV" >> "$GITHUB_OUTPUT" | ||
| echo "has_base=true" >> "$GITHUB_OUTPUT" | ||
| echo "::notice::INFO: Baseline tag detected: $PREV" | ||
| else | ||
| echo "has_base=false" >> "$GITHUB_OUTPUT" | ||
| echo "::warning::WARN: No baseline tag found. Compare step will be skipped." | ||
| fi | ||
| - name: Docker Scout run (CRITICAL/HIGH, non-blocking) | ||
| uses: docker/scout-action@v1 | ||
| with: | ||
| command: quickview,cves | ||
| image: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| write-comment: false | ||
| summary: true | ||
| only-severities: critical,high | ||
| exit-code: false | ||
| - name: Docker Scout SARIF (all severities) | ||
| uses: docker/scout-action@v1 | ||
| with: | ||
| command: quickview,cves | ||
| image: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| sarif-file: scout.sarif | ||
| write-comment: false | ||
| summary: true | ||
| only-severities: critical,high,medium | ||
| - name: Docker Scout compare with previous tag | ||
| if: steps.base.outputs.has_base == 'true' | ||
| uses: docker/scout-action@v1 | ||
| with: | ||
| command: compare | ||
| image: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| to: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ steps.base.outputs.base_tag }} | ||
| write-comment: false | ||
| summary: true | ||
| - name: Trim Scout SARIF (limit locations) | ||
| run: | | ||
| jq ' | ||
| .runs[0].results |= map( | ||
| if (.locations | length) > 1000 | ||
| then .locations = (.locations[:1000]) | . | ||
| else . | ||
| end | ||
| ) | ||
| ' scout.sarif > scout.limited.sarif | ||
| - name: Upload Scout SARIF | ||
| uses: github/codeql-action/upload-sarif@v4 | ||
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false | ||
| with: | ||
| sarif_file: scout.limited.sarif | ||
| category: docker-scout | ||
| - name: Trivy scan (non-blocking) | ||
| uses: aquasecurity/trivy-action@0.33.1 | ||
| with: | ||
| image-ref: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| format: table | ||
| ignore-unfixed: true | ||
| vuln-type: 'os,library' | ||
| severity: 'CRITICAL,HIGH' | ||
| exit-code: 0 | ||
| - name: Trivy SARIF (all severities) | ||
| uses: aquasecurity/trivy-action@0.33.1 | ||
| with: | ||
| image-ref: ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| format: sarif | ||
| output: trivy.sarif | ||
| ignore-unfixed: true | ||
| vuln-type: 'os,library' | ||
| severity: 'CRITICAL,HIGH,MEDIUM' | ||
| exit-code: 0 | ||
| - name: Trim Trivy SARIF (limit locations) | ||
| run: | | ||
| jq ' | ||
| .runs[0].results |= map( | ||
| if (.locations | length) > 1000 | ||
| then .locations = (.locations[:1000]) | . | ||
| else . | ||
| end | ||
| ) | ||
| ' trivy.sarif > trivy.limited.sarif | ||
| - name: Upload Trivy SARIF | ||
| uses: github/codeql-action/upload-sarif@v4 | ||
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false | ||
| with: | ||
| sarif_file: trivy.limited.sarif | ||
| category: trivy | ||
| - name: Push release tags (after successful scans) | ||
| run: | | ||
| set -euo pipefail | ||
| echo "::notice::INFO: Pushing release tags to Docker Hub." | ||
| docker push ${{ env.DOCKER_USER }}/enshrouded_server_docker:latest | ||
| docker push ${{ env.DOCKER_USER }}/enshrouded_server_docker:${{ github.event.release.tag_name }} | ||
| echo "::notice::SUCCESS: Push complete." | ||
| update-readme: | ||
| needs: build-release | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| DOCKER_USER: ${{ secrets.DOCKER_USER }} | ||
| DOCKER_TOKEN: ${{ secrets.DOCKER_TOKEN }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Skip description update (password missing) | ||
| if: env.DOCKER_TOKEN == '' | ||
| run: echo "::warning::WARN: DOCKER_TOKEN secret is missing; skipping description update." | ||
| - name: Update Docker Hub description | ||
| if: env.DOCKER_TOKEN != '' | ||
| uses: peter-evans/dockerhub-description@v5 | ||
| with: | ||
| username: ${{ env.DOCKER_USER }} | ||
| password: ${{ env.DOCKER_TOKEN }} | ||
| repository: ${{ env.DOCKER_USER }}/enshrouded_server_docker | ||
| readme-filepath: docs/README_DOCKER_HUB.md | ||