#/ # @license Apache-2.0 # # Copyright (c) 2024 The Stdlib Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #/ # Workflow name: name: slash_commands # Workflow triggers: on: issue_comment: types: - created - edited # Workflow jobs: jobs: # Define a job for adding an initial reaction: add_initial_reaction: # Define a display name: name: 'Add initial reaction' # Define the type of virtual host machine: runs-on: ubuntu-latest # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib') # Define the job's steps: steps: # Add "bot: In progress" label to the issue / PR: - name: 'Add in-progress label' # Pin action to full length commit SHA uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} script: | github.rest.issues.addLabels({ 'owner': context.repo.owner, 'repo': context.repo.repo, 'issue_number': context.issue.number, 'labels': ['bot: In Progress'] }) # Add initial reaction to comment with slash command: - name: 'Add initial reaction' uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} script: | const commentBody = context.payload.comment.body.trim(); const RE_COMMANDS = /^\/stdlib\s+(help|check-files|update-copyright-years|lint-autofix|merge|rebase|make-commands)$/i; const isRecognizedCommand = RE_COMMANDS.test( commentBody ); if ( isRecognizedCommand ) { await github.rest.reactions.createForIssueComment({ 'owner': context.repo.owner, 'repo': context.repo.repo, 'comment_id': context.payload.comment.id, 'content': 'eyes' }); } else { // Include the full user comment as a Markdown quote block in response: const lines = commentBody.split( '\n' ); const quote = lines.map( line => `> ${line}` ).join( '\n' ); await github.rest.issues.createComment({ 'owner': context.repo.owner, 'repo': context.repo.repo, 'issue_number': context.issue.number, 'body': `${quote}\n\n@${context.payload.comment.user.login}, slash command not recognized. Please use \`/stdlib help\` to view available commands.` }); } # Define a job for checking for required files: check_files: # Define a display name: name: 'Check for required files' # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib check-files') # Run reusable workflow: uses: ./.github/workflows/check_required_files.yml with: pull_request_number: ${{ github.event.issue.number }} user: ${{ github.event.comment.user.login }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} # Define a command for leaving a comment with make command instructions: make-commands: # Define a display name: name: 'Post a comment with make command instructions' # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib make-commands') # Run reusable workflow: uses: ./.github/workflows/pr_commands_comment.yml with: pull_request_number: ${{ github.event.issue.number }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} # Define a job for updating copyright header years: update_copyright_years: # Define a display name: name: 'Update copyright header years' # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib update-copyright-years') # Run reusable workflow: uses: ./.github/workflows/update_pr_copyright_years.yml with: pull_request_number: ${{ github.event.issue.number }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }} STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }} # Define a job for auto-fixing lint errors: fix_lint_errors: # Define a display name: name: 'Auto-fix lint errors' # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib lint-autofix') # Run reusable workflow: uses: ./.github/workflows/lint_autofix.yml with: pull_request_number: ${{ github.event.issue.number }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }} STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }} # Define a job for merging develop branch: merge_develop: # Define a display name: name: 'Merge changes from develop branch into this PR' # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib merge') # Run reusable workflow: uses: ./.github/workflows/pr_merge_develop.yml with: pull_request_number: ${{ github.event.issue.number }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }} STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }} # Define a job for rebasing on develop branch: rebase_develop: # Define a display name: name: 'Rebase this PR on top of develop branch' # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib rebase') # Run reusable workflow: uses: ./.github/workflows/pr_rebase_develop.yml with: pull_request_number: ${{ github.event.issue.number }} secrets: STDLIB_BOT_GITHUB_TOKEN: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} STDLIB_BOT_GPG_PRIVATE_KEY: ${{ secrets.STDLIB_BOT_GPG_PRIVATE_KEY }} STDLIB_BOT_GPG_PASSPHRASE: ${{ secrets.STDLIB_BOT_GPG_PASSPHRASE }} # Define a job for printing a list of available slash commands: help: # Define a display name: name: 'Print a list of available slash commands' # Define the type of virtual host machine: runs-on: ubuntu-latest # Ensure initial reaction job has completed before running this job: needs: [ add_initial_reaction ] # Define the conditions under which the job should run: if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib help') # Define the job's steps: steps: # Create a comment on the pull request informing the user of available slash commands: - name: 'Create a comment on the pull request informing the user of available slash commands' # Pin action to full length commit SHA uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 with: # Specify the issue or pull request number: issue-number: ${{ github.event.issue.number }} # Specify the comment body: body: | @${{ github.event.comment.user.login }}, available slash commands include: - `/stdlib check-files` - Check for required files. - `/stdlib make-commands` - Print `make` commands for package changed in PR. - `/stdlib update-copyright-years` - Update copyright header years. - `/stdlib lint-autofix` - Auto-fix lint errors. - `/stdlib merge` - Merge changes from develop branch into this PR. - `/stdlib rebase` - Rebase this PR on top of develop branch. # GitHub token: token: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} # Define a job for removing the in-progress label: remove_progress_label: # Define a display name: name: 'Remove in-progress label' # Define the type of virtual host machine: runs-on: ubuntu-latest # Ensure all previous jobs have completed before running this job: needs: [ add_initial_reaction, check_files, make-commands, update_copyright_years, fix_lint_errors, merge_develop, rebase_develop, help ] # Define the conditions under which the job should run: if: | always() && github.event.issue.pull_request && startsWith(github.event.comment.body, '/stdlib') # Define the job's steps: steps: # Check if any previous job failed and post a comment: - name: 'Notify of command failure' if: | contains(needs.*.result, 'failure') uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} script: | const commentBody = context.payload.comment.body.trim(); const lines = commentBody.split( '\n' ); const quote = lines.map( line => `> ${line}` ).join( '\n' ); await github.rest.issues.createComment({ 'owner': context.repo.owner, 'repo': context.repo.repo, 'issue_number': context.issue.number, 'body': `${quote}\n\n@${context.payload.comment.user.login}, the slash command failed to complete. Please check the workflow logs for details.\n\n[View workflow run](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})` }); - name: Remove in-progress label # Run the step regardless of the outcome of previous steps: if: always() # Pin action to full length commit SHA uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.STDLIB_BOT_PAT_REPO_WRITE }} script: | try { await github.rest.issues.removeLabel({ 'owner': context.repo.owner, 'repo': context.repo.repo, 'issue_number': context.issue.number, 'name': 'bot: In Progress' }) } catch ( error ) { console.log( 'Error removing label: %s', error.message ); }