diff --git a/workflow-templates/command-openapi.properties.json b/workflow-templates/command-openapi.properties.json new file mode 100644 index 0000000..5570eac --- /dev/null +++ b/workflow-templates/command-openapi.properties.json @@ -0,0 +1,5 @@ +{ + "name": "Regenerate OpenAPI workflow", + "description": "Regenerate and commit OpenAPI assets.\nExample: `/openapi [[rebase][-][amend|fixup]]`", + "iconName": "openapi" +} diff --git a/workflow-templates/command-openapi.yml b/workflow-templates/command-openapi.yml new file mode 100644 index 0000000..78f2e0e --- /dev/null +++ b/workflow-templates/command-openapi.yml @@ -0,0 +1,194 @@ +# This workflow is provided via the organization template repository +# +# https://github.com/nextcloud/.github +# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization +# +# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors +# SPDX-License-Identifier: MIT + +name: OpenAPI Command +on: + issue_comment: + types: [created] + +jobs: + init: + runs-on: ubuntu-latest + + # On pull requests and if the comment starts with `/openapi` + if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/openapi') + + outputs: + git_path: ${{ steps.git-path.outputs.path }} + arg1: ${{ steps.command.outputs.arg1 }} + arg2: ${{ steps.command.outputs.arg2 }} + head_ref: ${{ steps.comment-branch.outputs.head_ref }} + base_ref: ${{ steps.comment-branch.outputs.base_ref }} + + steps: + - name: Get repository from pull request comment + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + id: get-repository + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const pull = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number + }); + + const repositoryName = pull.data.head?.repo?.full_name + console.log(repositoryName) + return repositoryName + + - name: Disabled on forks + if: ${{ fromJSON(steps.get-repository.outputs.result) != github.repository }} + run: | + echo 'Can not execute /openapi on forks' + exit 1 + + - name: Check actor permission + uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v2 + with: + require: write + + - name: Add reaction on start + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + repository: ${{ github.event.repository.full_name }} + comment-id: ${{ github.event.comment.id }} + reactions: '+1' + + - name: Parse command + uses: skjnldsv/parse-command-comment@5c955203c52424151e6d0e58fb9de8a9f6a605a1 # v2 + id: command + + # Init path depending on which command is run + - name: Init path + id: git-path + run: | + if ${{ startsWith(steps.command.outputs.arg1, '/') }}; then + echo "path=${{steps.command.outputs.arg1}}" >> $GITHUB_OUTPUT + else + echo "path=${{steps.command.outputs.arg2}}" >> $GITHUB_OUTPUT + fi + + - name: Init branch + uses: xt0rted/pull-request-comment-branch@d97294d304604fa98a2600a6e2f916a84b596dc7 # v1 + id: comment-branch + + - name: Add reaction on failure + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + if: failure() + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + repository: ${{ github.event.repository.full_name }} + comment-id: ${{ github.event.comment.id }} + reactions: '-1' + + process: + runs-on: ubuntu-latest + needs: init + + steps: + - name: Restore cached git repository + uses: buildjet/cache@e376f15c6ec6dc595375c78633174c7e5f92dc0e # v3 + with: + path: .git + key: git-repo + + - name: Checkout ${{ needs.init.outputs.head_ref }} + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + fetch-depth: 0 + ref: ${{ needs.init.outputs.head_ref }} + + - name: Setup git + run: | + git config --local user.email 'nextcloud-command@users.noreply.github.com' + git config --local user.name 'nextcloud-command' + + - name: Check Typescript OpenApi types + id: check_typescript_openapi + uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0 + with: + files: "src/types/openapi/openapi*.ts" + + - name: Read package.json node and npm engines version + if: steps.check_typescript_openapi.outputs.files_exists == 'true' + uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 + id: node_versions + # Continue if no package.json + continue-on-error: true + with: + fallbackNode: '^20' + fallbackNpm: '^10' + + - name: Set up node ${{ steps.node_versions.outputs.nodeVersion }} + if: ${{ steps.node_versions.outputs.nodeVersion }} + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + with: + node-version: ${{ steps.node_versions.outputs.nodeVersion }} + + - name: Set up npm ${{ steps.node_versions.outputs.npmVersion }} + if: ${{ steps.node_versions.outputs.nodeVersion }} + run: npm i -g 'npm@${{ steps.node_versions.outputs.npmVersion }}' + + - name: Rebase to ${{ needs.init.outputs.base_ref }} + if: ${{ contains(needs.init.outputs.arg1, 'rebase') }} + run: | + git fetch origin '${{ needs.init.outputs.base_ref }}:${{ needs.init.outputs.base_ref }}' + git rebase 'origin/${{ needs.init.outputs.base_ref }}' + + - name: Install dependencies + env: + CYPRESS_INSTALL_BINARY: 0 + PUPPETEER_SKIP_DOWNLOAD: true + run: | + npm ci + + - name: Set up dependencies + run: composer i + + - name: Regenerate OpenAPI + run: composer run openapi + + - name: Commit default + if: ${{ !contains(needs.init.outputs.arg1, 'fixup') && !contains(needs.init.outputs.arg1, 'amend') }} + run: | + git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}' + git commit --signoff -m 'fix(openapi): Regenerate OpenAPI assets' + + - name: Commit fixup + if: ${{ contains(needs.init.outputs.arg1, 'fixup') }} + run: | + git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}' + git commit --fixup=HEAD --signoff + + - name: Commit amend + if: ${{ contains(needs.init.outputs.arg1, 'amend') }} + run: | + git add '${{ github.workspace }}${{ needs.init.outputs.git_path }}' + git commit --amend --no-edit --signoff + # Remove any [skip ci] from the amended commit + git commit --amend -m "$(git log -1 --format='%B' | sed '/\[skip ci\]/d')" + + - name: Push normally + if: ${{ !contains(needs.init.outputs.arg1, 'rebase') && !contains(needs.init.outputs.arg1, 'amend') }} + run: git push origin '${{ needs.init.outputs.head_ref }}' + + - name: Force push + if: ${{ contains(needs.init.outputs.arg1, 'rebase') || contains(needs.init.outputs.arg1, 'amend') }} + run: git push --force origin '${{ needs.init.outputs.head_ref }}' + + - name: Add reaction on failure + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + if: failure() + with: + token: ${{ secrets.COMMAND_BOT_PAT }} + repository: ${{ github.event.repository.full_name }} + comment-id: ${{ github.event.comment.id }} + reactions: '-1' diff --git a/workflow-templates/openapi.yml b/workflow-templates/openapi.yml index 7756a2c..12b233f 100644 --- a/workflow-templates/openapi.yml +++ b/workflow-templates/openapi.yml @@ -68,7 +68,7 @@ jobs: if: ${{ steps.node_versions.outputs.nodeVersion }} run: npm i -g 'npm@${{ steps.node_versions.outputs.npmVersion }}' - - name: Install dependencies & build + - name: Install dependencies if: ${{ steps.node_versions.outputs.nodeVersion }} env: CYPRESS_INSTALL_BINARY: 0