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@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
      - name: Setup .NET
        uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # tag=v3
        with:
          dotnet-version: '7.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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
        with:
          name: openapi-head
          retention-days: 14
          if-no-files-found: error
          path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net7.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@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          fetch-depth: 0
      - name: Checkout common ancestor
        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/${{ github.head_ref }})
          git checkout --progress --force $ANCESTOR_REF
      - name: Setup .NET
        uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # tag=v3
        with:
          dotnet-version: '7.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@0b7f8abb1508181956e8e162db84b466c27e18ce # v3
        with:
          name: openapi-base
          retention-days: 14
          if-no-files-found: error
          path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net7.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@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
        with:
          name: openapi-head
          path: openapi-head
      - name: Download openapi-base
        uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3
        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@81e2da3af01c92f83cb927cf3ace0e085617c556 # v2
        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@5adcb0bb0f9fb3f95ef05400558bdb3f329ee808 # tag=v2
        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@5adcb0bb0f9fb3f95ef05400558bdb3f329ee808 # tag=v2
        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.