name: OpenAPI
on:
  push:
    branches:
      - master
  pull_request_target:

permissions: {}

jobs:
  openapi-head:
    name: OpenAPI - HEAD
    runs-on: ubuntu-latest
    permissions: read-all
    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
      - name: Setup .NET
        uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
        with:
          dotnet-version: '8.0.x'
      - name: Generate openapi.json
        run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
      - name: Upload openapi.json
        uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
        with:
          name: openapi-head
          retention-days: 14
          if-no-files-found: error
          path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net8.0/openapi.json

  openapi-base:
    name: OpenAPI - BASE
    if: ${{ github.base_ref != '' }}
    runs-on: ubuntu-latest
    permissions: read-all
    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          fetch-depth: 0
      - name: Checkout common ancestor
        env:
          HEAD_REF: ${{ github.head_ref }}
        run: |
          git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }}
          git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/*
          ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF)
          git checkout --progress --force $ANCESTOR_REF
      - name: Setup .NET
        uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
        with:
          dotnet-version: '8.0.x'
      - name: Generate openapi.json
        run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests"
      - name: Upload openapi.json
        uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
        with:
          name: openapi-base
          retention-days: 14
          if-no-files-found: error
          path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net8.0/openapi.json

  openapi-diff:
    permissions:
      pull-requests: write  #  to create or update comment (peter-evans/create-or-update-comment)

    name: OpenAPI - Difference
    if: ${{ github.event_name == 'pull_request_target' }}
    runs-on: ubuntu-latest
    needs:
      - openapi-head
      - openapi-base
    steps:
      - name: Download openapi-head
        uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
        with:
          name: openapi-head
          path: openapi-head
      - name: Download openapi-base
        uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4
        with:
          name: openapi-base
          path: openapi-base
      - name: Workaround openapi-diff issue
        run: |
          sed -i 's/"allOf"/"oneOf"/g' openapi-head/openapi.json
          sed -i 's/"allOf"/"oneOf"/g' openapi-base/openapi.json
      - name: Calculate OpenAPI difference
        uses: docker://openapitools/openapi-diff
        continue-on-error: true
        with:
          args: --fail-on-changed --markdown openapi-changes.md openapi-base/openapi.json openapi-head/openapi.json
      - id: read-diff
        name: Read openapi-diff output
        run: |
          body=$(cat openapi-changes.md)
          body="${body//'%'/'%25'}"
          body="${body//$'\n'/'%0A'}"
          body="${body//$'\r'/'%0D'}"
          echo ::set-output name=body::$body
      - name: Find difference comment
        uses: peter-evans/find-comment@d5fe37641ad8451bdd80312415672ba26c86575e # v3.0.0
        id: find-comment
        with:
          issue-number: ${{ github.event.pull_request.number }}
          direction: last
          body-includes: openapi-diff-workflow-comment
      - name: Reply or edit difference comment (changed)
        uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
        if: ${{ steps.read-diff.outputs.body != '' }}
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-id: ${{ steps.find-comment.outputs.comment-id }}
          edit-mode: replace
          body: |
            <!--openapi-diff-workflow-comment-->
            <details>
            <summary>Changes in OpenAPI specification found. Expand to see details.</summary>

            ${{ steps.read-diff.outputs.body }}

            </details>
      - name: Edit difference comment (unchanged)
        uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
        if: ${{ steps.read-diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }}
        with:
          issue-number: ${{ github.event.pull_request.number }}
          comment-id: ${{ steps.find-comment.outputs.comment-id }}
          edit-mode: replace
          body: |
            <!--openapi-diff-workflow-comment-->

            No changes to OpenAPI specification found. See history of this comment for previous changes.
