name: Command on: issue_comment: # listen for comments on issues types: [created] permissions: # allow the action to comment in PR contents: read issues: write pull-requests: write actions: read jobs: is-org-member: if: startsWith(github.event.comment.body, '/cmd') runs-on: ubuntu-latest outputs: member: ${{ steps.is-member.outputs.result }} steps: - name: Generate token id: generate_token uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.CMD_BOT_APP_ID }} private-key: ${{ secrets.CMD_BOT_APP_KEY }} - name: Check if user is a member of the organization id: is-member uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ steps.generate_token.outputs.token }} result-encoding: string script: | const fs = require("fs"); try { const org = '${{ github.event.repository.owner.login }}'; const username = '${{ github.event.comment.user.login }}'; const membership = await github.rest.orgs.checkMembershipForUser({ org: org, username: username }); console.log(membership, membership.status, membership.status === 204); if (membership.status === 204) { return 'true'; } else { console.log(membership); fs.appendFileSync(process.env["GITHUB_STEP_SUMMARY"], `${membership.data && membership.data.message || 'Unknown error happened, please check logs'}`); } } catch (error) { console.log(error) } return 'false'; acknowledge: if: ${{ startsWith(github.event.comment.body, '/cmd') }} runs-on: ubuntu-latest steps: - name: Add reaction to triggered comment uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | github.rest.reactions.createForIssueComment({ comment_id: ${{ github.event.comment.id }}, owner: context.repo.owner, repo: context.repo.repo, content: 'eyes' }) clean: runs-on: ubuntu-latest steps: - name: Clean previous comments uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--clean') }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | github.rest.issues.listComments({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo }).then(comments => { for (let comment of comments.data) { console.log(comment) if ( ${{ github.event.comment.id }} !== comment.id && ( ( ( comment.body.startsWith('Command') || comment.body.startsWith('
Command') || comment.body.startsWith('Sorry, only ') ) && comment.user.type === 'Bot' ) || (comment.body.startsWith('/cmd') && comment.user.login === context.actor) ) ) { github.rest.issues.deleteComment({ comment_id: comment.id, owner: context.repo.owner, repo: context.repo.repo }) } } }) get-pr-info: if: ${{ startsWith(github.event.comment.body, '/cmd') }} runs-on: ubuntu-latest outputs: CMD: ${{ steps.get-comment.outputs.group2 }} pr-branch: ${{ steps.get-pr.outputs.pr_branch }} repo: ${{ steps.get-pr.outputs.repo }} steps: - name: Get command uses: actions-ecosystem/action-regex-match@9e6c4fb3d5e898f505be7a1fb6e7b0a278f6665b # v2.0.2 id: get-comment with: text: ${{ github.event.comment.body }} regex: "^(\\/cmd )([-\\/\\s\\w.=:]+)$" # see explanation in docs/contributor/commands-readme.md#examples # Get PR branch name, because the issue_comment event does not contain the PR branch name - name: Check if the issue is a PR id: check-pr run: | if [ -n "${{ github.event.issue.pull_request.url }}" ]; then echo "This is a pull request comment" else echo "This is not a pull request comment" exit 1 fi - name: Get PR Branch Name and Repo if: steps.check-pr.outcome == 'success' id: get-pr uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const pr = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number, }); const prBranch = pr.data.head.ref; const repo = pr.data.head.repo.full_name; console.log(prBranch, repo) core.setOutput('pr_branch', prBranch); core.setOutput('repo', repo); - name: Use PR Branch Name and Repo env: PR_BRANCH: ${{ steps.get-pr.outputs.pr_branch }} REPO: ${{ steps.get-pr.outputs.repo }} CMD: ${{ steps.get-comment.outputs.group2 }} run: | echo "The PR branch is $PR_BRANCH" echo "The repository is $REPO" echo "The CMD is $CMD" help: needs: [clean, get-pr-info] if: ${{ startsWith(github.event.comment.body, '/cmd') && contains(github.event.comment.body, '--help') }} runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Save output of help id: help env: CMD: ${{ needs.get-pr-info.outputs.CMD }} # to avoid "" around the command run: | python3 -m pip install -r .github/scripts/generate-prdoc.requirements.txt echo 'help<> $GITHUB_OUTPUT python3 .github/scripts/cmd/cmd.py $CMD >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT - name: Comment PR (Help) uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `
Command help: \`\`\` ${{ steps.help.outputs.help }} \`\`\`
` }) - name: Add confused reaction on failure uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 if: ${{ failure() }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | github.rest.reactions.createForIssueComment({ comment_id: ${{ github.event.comment.id }}, owner: context.repo.owner, repo: context.repo.repo, content: 'confused' }) - name: Add 👍 reaction on success uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 if: ${{ !failure() }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | github.rest.reactions.createForIssueComment({ comment_id: ${{ github.event.comment.id }}, owner: context.repo.owner, repo: context.repo.repo, content: '+1' }) set-image: needs: [clean, get-pr-info] if: ${{ startsWith(github.event.comment.body, '/cmd') && !contains(github.event.comment.body, '--help') }} runs-on: ubuntu-latest env: CMD: ${{ needs.get-pr-info.outputs.CMD }} outputs: IMAGE: ${{ steps.set-image.outputs.IMAGE }} RUNNER: ${{ steps.set-image.outputs.RUNNER }} steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - id: set-image run: | BODY=$(echo "$CMD" | xargs) # remove whitespace IMAGE_OVERRIDE=$(echo $BODY | grep -oe 'docker.io/pezkuwichain/ci-unified:.*\s' | xargs) cat .github/env >> $GITHUB_OUTPUT if [ -n "$IMAGE_OVERRIDE" ]; then IMAGE=$IMAGE_OVERRIDE echo "IMAGE=$IMAGE" >> $GITHUB_OUTPUT fi # Use GitHub-hosted runners for Pezkuwi SDK echo "RUNNER=ubuntu-latest" >> $GITHUB_OUTPUT - name: Print outputs run: | echo "RUNNER=${{ steps.set-image.outputs.RUNNER }}" echo "IMAGE=${{ steps.set-image.outputs.IMAGE }}" check-pr-author: runs-on: ubuntu-latest outputs: is_author: ${{ steps.check-author.outputs.result }} steps: - name: Generate token id: generate_token uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 with: app-id: ${{ secrets.CMD_BOT_APP_ID }} private-key: ${{ secrets.CMD_BOT_APP_KEY }} - name: Check if user is PR author id: check-author uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ steps.generate_token.outputs.token }} result-encoding: string script: | const commentUser = '${{ github.event.comment.user.login }}'; const prNumber = ${{ github.event.issue.number }}; try { const pr = await github.rest.pulls.get({ owner: context.repo.owner, repo: context.repo.repo, pull_number: prNumber }); const prAuthor = pr.data.user.login; return commentUser === prAuthor ? 'true' : 'false'; } catch (error) { console.error('Error checking PR author:', error); return 'false'; } run-cmd-workflow: needs: [set-image, get-pr-info, is-org-member, check-pr-author] runs-on: ubuntu-latest # don't run on help command if: ${{ startsWith(github.event.comment.body, '/cmd') && !contains(github.event.comment.body, '--help') }} permissions: # run workflow contents: read issues: write pull-requests: write actions: write env: CMD: ${{ needs.get-pr-info.outputs.CMD }} PR_BRANCH: ${{ needs.get-pr-info.outputs.pr-branch }} RUNNER: ${{ needs.set-image.outputs.RUNNER }} IMAGE: ${{ needs.set-image.outputs.IMAGE }} REPO: ${{ needs.get-pr-info.outputs.repo }} IS_ORG_MEMBER: ${{ needs.is-org-member.outputs.member }} IS_PR_AUTHOR: ${{ needs.check-pr-author.outputs.is_author }} COMMENT_ID: ${{ github.event.comment.id }} PR_NUMBER: ${{ github.event.issue.number }} steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Start cmd with gh cli env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh workflow run cmd-run.yml \ --ref cmd-bot \ -f cmd="${CMD}" \ -f repo="${REPO}" \ -f pr_branch="${PR_BRANCH}" \ -f pr_num="${PR_NUMBER}" \ -f runner="${RUNNER}" \ -f is_org_member="${IS_ORG_MEMBER}" \ -f is_pr_author="${IS_PR_AUTHOR}" \ -f comment_id="${COMMENT_ID}" \ -f image="${IMAGE}" \ -f is_quiet="${{ contains(github.event.comment.body, '--quiet') }}"