Setting GitHub actions is a headache, and it takes time to run correctly. I’ll share what actions I daily use.

How to add github actions?

Add github actions on your branch

  • .github/workflows/xxxx.yml
github action

Trigger github action by leaving a comment on PR

Scenario 1: share new build to someone

You can define commands to run action

For example, If you want to share something to test, use this action.

  • share is command
  • test is userId

And you can leave a comment using github.issues.createComment

This action is very useful. You can integrate third-party services like Slack, WhatsApp, or Linear. Listening share command and trigger action whatever you want to share it.

name: Comment Action
on:
  issue_comment:
    types: [created]
jobs:
  comment_job:
    runs-on: ubuntu-latest
    steps:
      - name: Check Comment Type
        id: check_comment
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const comment = context.payload.comment.body.trim();
            console.log(`Received comment: ${comment}`);

            const issueOrPrNumber = context.payload.issue?.number || context.payload.pull_request?.number;
            if (!issueOrPrNumber) {
              throw new Error("Could not determine issue or PR number.");
            }

            let action = '';
            if (comment.startsWith('share')) {
              action = 'share';
            }

            core.setOutput('action', action);
            core.setOutput('comment', comment);
            core.setOutput('issue_or_pr_number', issueOrPrNumber);
      
      - name: Handle Share Command
        if: steps.check_comment.outputs.action == 'share'
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const comment = '${{ steps.check_comment.outputs.comment }}';
            const issueOrPrNumber = '${{ steps.check_comment.outputs.issue_or_pr_number }}';

            if (!issueOrPrNumber) {
              throw new Error("Could not determine the issue or PR number.");
            }

            const splitComment = comment.split(' ');
            if (splitComment.length < 2) {
              throw new Error("Invalid 'share' command format. Expected: 'share <id>'");
            }

            const recipientId = splitComment[1]; // Extract ID after "share"
            const commentBody = `Sharing this with: ${recipientId}`;

            console.log(`Adding a share comment for ID: ${recipientId}`);
            await github.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueOrPrNumber,
              body: commentBody
            });

scenario 2: rebuild when the build failed

There are 2 yml files in workflows

When you get a build failed message, you can rebuild it by leaving a comment.

github action

comment_action.yml

  • Get PR Number using github.pulls.get
  • Pass issue_or_pr_number as Inputs to build.yml
name: Comment Action
on:
  issue_comment:
    types: [created]

jobs:
  comment_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: GitHub CLI Login
        run: |
          gh auth login --with-token <<< "${{ secrets.GITHUB_TOKEN }}"
      - name: Check Comment Type
        id: check_comment
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const comment = context.payload.comment.body.trim();
            console.log(`Received comment: ${comment}`);
        
            const issueOrPrNumber = context.payload.issue?.number || context.payload.pull_request?.number;
            const isPR = Boolean(context.payload.issue.pull_request);

            if (!isPR) {
              throw new Error("This comment is not associated with a pull request.");
            }

            const { data: pullRequest } = await github.pulls.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: issueOrPrNumber,
            });

            const sourceBranch = pullRequest.head.ref;
            const targetBranch = pullRequest.base.ref;

            console.log(`Source branch: ${sourceBranch}`);
            console.log(`Target branch: ${targetBranch}`);
            if (!issueOrPrNumber) {
              throw new Error("Could not determine issue or PR number.");
            }

            let action = '';
            if (comment === 'rebuild') {
              action = 'rebuild';
            }

            core.setOutput('action', action);
            core.setOutput('comment', comment);
            core.setOutput('issue_or_pr_number', issueOrPrNumber);
            core.setOutput('source_branch', sourceBranch);
            core.setOutput('target_branch', targetBranch);

      - name: Rebuild
        run: |
          echo "🟢 Issue or PR Number: ${{ steps.check_comment.outputs.issue_or_pr_number }}"
          gh workflow run rebuild.yml --ref ${{ steps.check_comment.outputs.target_branch }} -f issue_or_pr_number=${{ steps.check_comment.outputs.issue_or_pr_number }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build.yml

  • define workflow_dispatch and inputs
name: build

on:
  workflow_dispatch:
    inputs:
      issue_or_pr_number:
        description: "The issue or PR number to comment on"
        required: true

jobs:
  reusable_job:
    runs-on: ubuntu-latest
    steps:
      - name: Build
        run: echo "Running workflow"
      - name: Rebuild triggered
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueOrPrNumber = ${{ github.event.inputs.issue_or_pr_number }};
            console.log(`🟢 Input issue_or_pr_number: ${issueOrPrNumber}`);
            if (!issueOrPrNumber) {
              throw new Error("Could not determine the issue or PR number.");
            }
            const commentBody = `Rebuild triggered`;
            await github.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueOrPrNumber,
              body: commentBody
            });

scenario 3: read latest build success message and share it to someone

build.yml

  • Just leave a comment on PR
name: Build

on:
  pull_request:
    branches:
      - master
    types:
      - opened
      - synchronize
      - reopened
      - edited
jobs:
  run_on_pr:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - name: Comment on PR
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueOrPrNumber = context.payload.pull_request.number;
            console.log(issueOrPrNumber);

            await github.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueOrPrNumber,
              body: "iOS v12.0(1022)"
            });

            await github.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueOrPrNumber,
              body: "Android 15.0(1022)"
            });

comment_action.yml

  • await github.issues.listComments
    • default page_num is 30. If your PR have many comments, I suggest you set page_num 100
name: Comment Action
on:
  issue_comment:
    types: [created]

jobs:
  comment_job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: GitHub CLI Login
        run: |
          gh auth login --with-token <<< "${{ secrets.GITHUB_TOKEN }}"
      - name: Check Comment Type
        id: check_comment
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const comment = context.payload.comment.body.trim();
            console.log(`Received comment: ${comment}`);
        
            const issueOrPrNumber = context.payload.issue?.number || context.payload.pull_request?.number;
            const isPR = Boolean(context.payload.issue.pull_request);

            if (!isPR) {
              throw new Error("This comment is not associated with a pull request.");
            }

            const { data: pullRequest } = await github.pulls.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: issueOrPrNumber
            });

            const sourceBranch = pullRequest.head.ref;
            const targetBranch = pullRequest.base.ref;

            console.log(`Source branch: ${sourceBranch}`);
            console.log(`Target branch: ${targetBranch}`);

            core.setOutput('source_branch', sourceBranch);
            core.setOutput('target_branch', targetBranch);
            if (!issueOrPrNumber) {
              throw new Error("Could not determine issue or PR number.");
            }

            let action = '';
            if (comment.startsWith('share')) {
              action = 'share';
            }

            core.setOutput('action', action);
            core.setOutput('comment', comment);
            core.setOutput('issue_or_pr_number', issueOrPrNumber);

      - name: Get Latest Build Comments
        if: steps.check_comment.outputs.action == 'share'
        uses: actions/github-script@v4
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumber = ${{ steps.check_comment.outputs.issue_or_pr_number }};
            const comment = '${{ steps.check_comment.outputs.comment }}';

            if (!issueNumber) {
              throw new Error("Could not determine the issue or PR number.");
            }

            const splitComment = comment.split(' ');
            if (splitComment.length < 2) {
              throw new Error("Invalid 'share' command format. Expected: 'share <id>'");
            }

            const recipientId = splitComment[1]; // Extract ID after "share"
            
            // Fetch all comments on the PR
            const comments = await github.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueNumber,
              per_page: 100,
            });

            console.log("✅ All Comments")
            comments.data.forEach(comment => console.log(`- ${comment.body}`));


            // Filter and find the most recent iOS-related comment
            const latestIOS = comments.data
              .filter(comment => comment.body.startsWith('iOS'))
              .sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at))[0];

            // Filter and find the most recent Android-related comment
            const latestAndroid = comments.data
              .filter(comment => comment.body.startsWith('Android'))
              .sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at))[0];

            if (latestIOS) {
              console.log(`Latest iOS Comment: ${latestIOS.body}`);
              core.setOutput('latest_ios_comment', latestIOS.body);
            } else {
              console.log('No iOS-related comments found.');
            }

            if (latestAndroid) {
              console.log(`Latest Android Comment: ${latestAndroid.body}`);
              core.setOutput('latest_android_comment', latestAndroid.body);
            } else {
              console.log('No Android-related comments found.');
            }
            const commentBody = `Sharing this with: ${recipientId}\nReady for Testing\n${latestIOS.body}\n${latestAndroid.body}`;
            await github.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issueNumber,
              body: commentBody
            });

Leave a comment

Quote of the week

"People ask me what I do in the winter when there's no baseball. I'll tell you what I do. I stare out the window and wait for spring."

~ Rogers Hornsby