name: Post Dependabot

on:
  pull_request

permissions:
  contents: write

jobs:
  template-oss:
    {{> jobYml
      jobName="template-oss"
      jobIf="github.actor == 'dependabot[bot]'"
      jobCheckout=(obj ref="${{ github.event.pull_request.head.ref }}")
    }}
      - name: Fetch Dependabot Metadata
        id: metadata
        uses: dependabot/fetch-metadata@v1
        with:
          github-token: $\{{ secrets.GITHUB_TOKEN }}

      # Dependabot can update multiple directories so we output which directory
      # it is acting on so we can run the command for the correct root or workspace
      - name: Get Dependabot Directory
        if: contains(steps.metadata.outputs.dependency-names, '{{ __NAME__ }}')
        id: flags
        run: |
          dependabot_dir="$\{{ steps.metadata.outputs.directory }}"
          if [[ "$dependabot_dir" == "/" || "$dependabot_dir" == "/{{ releaseBranch }}" ]]; then
            echo "workspace=-iwr" >> $GITHUB_OUTPUT
          else
            # strip leading slash from directory so it works as a
            # a path to the workspace flag
            echo "workspace=--workspace ${dependabot_dir#/}" >> $GITHUB_OUTPUT
          fi

      - name: Apply Changes
        if: steps.flags.outputs.workspace
        id: apply
        run: |
          {{ rootNpmPath }} run template-oss-apply $\{{ steps.flags.outputs.workspace }}
          if [[ `git status --porcelain` ]]; then
            echo "changes=true" >> $GITHUB_OUTPUT
          fi
          # This only sets the conventional commit prefix. This workflow can't reliably determine
          # what the breaking change is though. If a BREAKING CHANGE message is required then
          # this PR check will fail and the commit will be amended with stafftools
          if [[ "$\{{ steps.metadata.outputs.update-type }}" == "version-update:semver-major" ]]; then
            prefix='feat!'
          else
            prefix='chore'
          fi
          echo "message=$prefix: postinstall for dependabot template-oss PR" >> $GITHUB_OUTPUT

      # This step will fail if template-oss has made any workflow updates. It is impossible
      # for a workflow to update other workflows. In the case it does fail, we continue
      # and then try to apply only a portion of the changes in the next step
      - name: Push All Changes
        if: steps.apply.outputs.changes
        id: push
        continue-on-error: true
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: |
          git commit -am "$\{{ steps.apply.outputs.message }}"
          git push

      # If the previous step failed, then reset the commit and remove any workflow changes
      # and attempt to commit and push again. This is helpful because we will have a commit
      # with the correct prefix that we can then --amend with @npmcli/stafftools later.
      - name: Push All Changes Except Workflows
        if: steps.apply.outputs.changes && steps.push.outcome == 'failure'
        env:
          GITHUB_TOKEN: $\{{ secrets.GITHUB_TOKEN }}
        run: |
          git reset HEAD~
          git checkout HEAD -- .github/workflows/
          git clean -fd .github/workflows/
          git commit -am "$\{{ steps.apply.outputs.message }}"
          git push

      # Check if all the necessary template-oss changes were applied. Since we continued
      # on errors in one of the previous steps, this check will fail if our follow up
      # only applied a portion of the changes and we need to followup manually.
      #
      # Note that this used to run `lint` and `postlint` but that will fail this action
      # if we've also shipped any linting changes separate from template-oss. We do
      # linting in another action, so we want to fail this one only if there are
      # template-oss changes that could not be applied.
      - name: Check Changes
        if: steps.apply.outputs.changes
        run: |
          {{ rootNpmPath }} exec --offline $\{{ steps.flags.outputs.workspace }} -- template-oss-check

      - name: Fail on Breaking Change
        if: steps.apply.outputs.changes && startsWith(steps.apply.outputs.message, 'feat!')
        run: |
          echo "This PR has a breaking change. Run 'npx -p @npmcli/stafftools gh template-oss-fix'"
          echo "for more information on how to fix this with a BREAKING CHANGE footer."
          exit 1
