name: Docker App - Rest Passthrough
permissions:
  contents: read
on:
  push:
    branches:
      - 'main'
    paths:
      - '.github/workflows/docker-app-rest-passthrough.yml'
      - 'docker-apps/rest-passthrough/**'
  pull_request:
  merge_group:
  schedule:
    - cron: '0 0 * * *'

jobs:
  # Removing this for now until I can confirm a couple things and ensure it works fully
  #  - Matt H
  # run-release:
  #   name: Run release script
  #   runs-on: ubuntu-latest
  #   if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
  #   steps:
  #     - name: Checkout repository
  #       uses: actions/checkout@v6
  #     - name: Git config
  #       run: |
  #         git config user.name github-actions
  #         git config user.email github-actions@github.com
  #     - name: Run release script
  #       run: |
  #         yarn install --immutable
  #         yarn release
  #         git push && git push --tags

  app-version:
    name: Get app version
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.package-version.outputs.current-version }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: get-npm-version
        id: package-version
        uses: martinbeentjes/npm-get-version-action@v1.3.1
        with:
          path: docker-apps/rest-passthrough

  build:
    name: Build docker image
    runs-on: ubuntu-latest
    needs: app-version
    permissions:
      contents: read
      actions: write
    steps:
      - uses: actions/checkout@v6
      - name: Cache Docker layers
        uses: actions/cache@v5
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-single-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-single-buildx
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Build and push
        uses: docker/build-push-action@v7
        with:
          push: false
          tags: 'discordeno/app-rest-passthrough:latest, discordeno/app-rest-passthrough:v${{ needs.app-version.outputs.version }}'
          context: docker-apps/rest-passthrough
          target: runner
          outputs: type=docker,dest=/tmp/rest-passthrough-image.tar
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
      - # Temp fix
        # https://github.com/docker/build-push-action/issues/252
        # https://github.com/moby/buildkit/issues/1896
        name: Move cache
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache
      - name: Upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: rest-passthrough-image
          path: /tmp/rest-passthrough-image.tar

  image-scan:
    name: Image scan
    runs-on: ubuntu-latest
    needs: build
    if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }}
    permissions: 
      contents: read
      security-events: write
      actions: read
    steps:
      - uses: actions/checkout@v6
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Download artifact
        uses: actions/download-artifact@v8
        with:
          name: rest-passthrough-image
          path: /tmp
      - name: Load Docker image
        run: docker load --input /tmp/rest-passthrough-image.tar

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@0.35.0
        with:
          image-ref: 'discordeno/app-rest-passthrough:latest'
          exit-code: '0'
          vuln-type: 'os,library'
          severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL'
          format: 'sarif'
          output: 'trivy-results.sarif'
      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Run Snyk to check Docker image for vulnerabilities
        continue-on-error: true
        uses: snyk/actions/docker@v1.0.0
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          image: 'discordeno/app-rest-passthrough:latest'
          args: --file=docker-apps/rest-passthrough/Dockerfile

      # Snyk will use a security-severify of "null" when the CVE didn't get an assigned score
      - name: Replace security-severity null for non assigned CVE scores
        run: |
          sed -i 's/"security-severity": "null"/"security-severity": "0"/g' snyk.sarif
          sed -i 's/"cvssv3_baseScore": null/"cvssv3_baseScore": 0/g' snyk.sarif

      # Snyk will test 3 projects and will use for ALL 3 the same tool driver name, which is not supported anymore by github/codeql-action/upload-sarif
      # So since there seem to be no way to tell the Snyk CLI (what the snyk/actions/docker actions actually runs) to use distict names or generate multiple
      # sarif file to then assign different categories to we need to modify the SARIF file itself before uploading it to make sure that each run described
      # by the sarif file has a unique tool name
      - name: Change the Snyk tool names to different names
        uses: actions/github-script@v8
        with:
          script: |
            const fs = require('fs');
            const filePath = 'snyk.sarif';
            const data = fs.readFileSync(filePath, 'utf8');
            const json = JSON.parse(data);

            let index = 0;
            for (const run of json.runs) {
              if (run.tool.driver.name === "Snyk Container") {
                run.tool.driver.name = `Snyk Container #${index++}`;
              }
            }

            fs.writeFileSync(filePath, JSON.stringify(json, null, 2));

      - name: Upload snyk scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: snyk.sarif
          category: snyk-report

  build-all-arch:
    name: Build image for all architectures
    needs: [build, app-version]
    if: ${{ github.event_name != 'schedule' }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Cache Docker layers
        uses: actions/cache@v5
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-single-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-single-buildx
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Build Docker image
        uses: docker/build-push-action@v7
        with:
          context: docker-apps/rest-passthrough
          push: false
          tags: 'discordeno/app-rest-passthrough:latest, discordeno/app-rest-passthrough:v${{ needs.app-version.outputs.version }}'
          # linux/s390x stuck at yarn install, remove it for now
          platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le
          target: runner
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
      - # Temp fix
        # https://github.com/docker/build-push-action/issues/252
        # https://github.com/moby/buildkit/issues/1896
        name: Move cache
        run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache

  publish:
    name: Publish image
    # needs: [run-release, build-all-arch, app-version]
    needs: [build-all-arch, app-version]
    if: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' }}
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Log in to the Container registry
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Build and push Docker image
        uses: docker/build-push-action@v7
        with:
          context: docker-apps/rest-passthrough
          push: true
          tags: 'ghcr.io/discordeno/app-rest-passthrough:latest, ghcr.io/discordeno/app-rest-passthrough:v${{ needs.app-version.outputs.version }}'
          # linux/s390x stuck at yarn install, remove it for now
          platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le
          target: runner
