Skip to content

TT-16103: trigger release to suggested branch after merge#127

Open
olamilekan000 wants to merge 1 commit into
mainfrom
trigger-release-to-releas-branch-after-suggestion
Open

TT-16103: trigger release to suggested branch after merge#127
olamilekan000 wants to merge 1 commit into
mainfrom
trigger-release-to-releas-branch-after-suggestion

Conversation

@olamilekan000
Copy link
Copy Markdown
Contributor

change adds a workflow for adding a comment to a merged PR. This comment will then inturn trigger a PR on the target branch

@probelabs
Copy link
Copy Markdown
Contributor

probelabs Bot commented May 14, 2026

This PR enhances the branch-suggestion workflow to automatically trigger releases after a pull request is merged. It introduces a new step that posts /release to <branch> comments for each of the required or recommended branches identified by the suggestion logic. This change automates the hand-off from code merge to the release process.

Files Changed Analysis

  • .github/workflows/branch-suggestion.yml: The workflow trigger is updated to include the closed event for pull requests, allowing it to act upon merges.
  • branch-suggestion/branch_suggestion.yml: A new conditional job, post-release-commands, is added. This job only runs if the PR was merged. It consumes the branch suggestions from a temporary file created by the preceding analyze-and-suggest step.
  • branch-suggestion/scripts/github/post-release-commands.js: This new script contains the core logic. It parses the suggestion results, filters for required and recommended branches (excluding master), and posts a unique, marker-based /release comment for each target branch to prevent duplicates.
  • branch-suggestion/scripts/github/__tests__/post-release-commands.test.js: Unit tests are added for the new post-release-commands.js script, covering various scenarios like skipping branches and handling existing comments.
  • branch-suggestion/scripts/github/github-api.js: Refactored to include a shared parseRepo function, improving code reuse.

Architecture & Impact Assessment

  • What this PR accomplishes: It automates the initiation of release processes by bridging the gap between the branch suggestion system and downstream release workflows. This reduces manual developer intervention and streamlines deployments.
  • Key technical changes introduced:
    • Conditional workflow execution based on the PR's merged state (github.event.pull_request.merged).
    • Passing state (the JSON results of branch analysis) between workflow jobs via the filesystem.
    • A new Node.js script that uses the GitHub API to perform "chat-ops" by programmatically posting comments that trigger other actions.
  • Affected system components: The primary impact is on the branch-suggestion reusable workflow. It also directly affects any downstream release automation (like the one in release-bot.yaml) that is configured to listen for /release comments.
graph TD
    subgraph "GitHub Actions: branch-suggestion.yml"
        A[PR Merged Event] --> B{Is PR Merged?};
        B -- Yes --> C[Job: analyze-and-suggest];
        C -- saves results --> D[File: /tmp/results.json];
        C --> E[Job: post-release-commands];
        E -- reads results --> D;
        E --> F[Execute post-release-commands.js];
    end

    subgraph "post-release-commands.js Script"
        G[Start] --> H{Parse suggestion results};
        H --> I{"Filter for 'required'/'recommended' branches"};
        I --> J[For each target branch];
        J --> K["Format '/release to <branch>' comment"];
        K --> L[Post comment to PR via GitHub API];
    end

    F --> G;
    L --> M((Downstream Release Workflow Triggered));

    style A fill:#d4edda,stroke:#c3e6cb
    style M fill:#d4edda,stroke:#c3e6cb
Loading

Scope Discovery & Context Expansion

The changes are well-contained within the branch-suggestion action. However, the impact extends to any repository that uses this reusable workflow. The automation's effectiveness depends on a separate, downstream process that listens for these specific /release command comments. This PR creates an automated bridge between the branch suggestion system and a release bot (e.g., the workflow defined in .github/workflows/release-bot.yaml), streamlining the entire path from code merge to deployment.

Metadata
  • Review Effort: 3 / 5
  • Primary Label: feature

Powered by Visor from Probelabs

Last updated: 2026-05-14T17:31:29.143Z | Triggered by: pr_updated | Commit: 6b0bc76

💡 TIP: You can chat with Visor using /visor ask <your question>

@probelabs
Copy link
Copy Markdown
Contributor

probelabs Bot commented May 14, 2026

Security Issues (1)

Severity Location Issue
🟡 Warning branch-suggestion/branch_suggestion.yml:104
The content of `/tmp/branch_suggestion_results.json` is passed as a command-line argument using `$(cat ...)`. This can lead to failures if the file content is large enough to exceed the system's maximum command-line argument length limit (`ARG_MAX`). While unlikely for this specific use case, it's a potential vector for a denial-of-service failure in the workflow.
💡 SuggestionModify the script to pass the file path as an argument and have the Node.js script read the file directly. This is a more robust and scalable pattern that avoids command-line length limitations.

In branch_suggestion.yml, change the call to:

node scripts/github/post-release-commands.js &#34;$REPO&#34; &#34;$PR_NUMBER&#34; /tmp/branch_suggestion_results.json

And in branch-suggestion/scripts/github/post-release-commands.js, update the main function to read the file:

import fs from &#39;fs&#39;;
// ...
async function main() {
  // ...
  try {
    const repository = args[0];
    const prNumber = parseInt(args[1], 10);
    const matchDataPath = args[2];
    const matchData = JSON.parse(fs.readFileSync(matchDataPath, &#39;utf-8&#39;));
    // ...
  } catch (error) {
    // ...
  }
}

Architecture Issues (1)

Severity Location Issue
🟡 Warning branch-suggestion/branch_suggestion.yml:93-142
The file path `/tmp/branch_suggestion_results.json` is hard-coded in both the `analyze-and-suggest` and `post-release-commands` steps. This creates a "magic string" dependency for passing state between steps. If this path ever needs to be changed, it must be manually updated in multiple places, which is error-prone.
💡 SuggestionTo improve maintainability and make the dependency explicit, define the file path as an environment variable at the job level. This centralizes the configuration and removes the hard-coded string from the step logic.
jobs:
  checks:
    # ...
    env:
      RESULTS_FILE: /tmp/branch_suggestion_results.json
    steps:
      # ...
      analyze-and-suggest:
        # ...
        exec: |
          # ...
          # Use the environment variable
          printf &#39;%s\n&#39; &#34;$MATCH_RESULT&#34; &gt; &#34;$RESULTS_FILE&#34;

      post-release-commands:
        # ...
        exec: |
          # ...
          # Use the environment variable
          if [ ! -f &#34;$RESULTS_FILE&#34; ]; then
            echo &#34;ℹ️  Results file not found. Skipping release commands.&#34; &gt;&amp;2
            exit 0
          fi

          node scripts/github/post-release-commands.js &#34;$REPO&#34; &#34;$PR_NUMBER&#34; &#34;$(cat &#34;$RESULTS_FILE&#34;)&#34;

          rm -f &#34;$RESULTS_FILE&#34;

Performance Issues (1)

Severity Location Issue
🟠 Error branch-suggestion/scripts/github/post-release-commands.js:58-86
The script repeatedly fetches all comments for a pull request inside a loop that iterates over target branches. This N+1 API call pattern is inefficient, can lead to hitting GitHub API rate limits, and will slow down the action, especially for PRs with many comments or multiple target release branches.
💡 SuggestionFetch all PR comments in a single API call before the loop. Then, iterate through the pre-fetched list of comments within the loop to check for existing release commands. This changes the pattern from N+1 API calls to just 1. You will also need to import `listPRComments` from `./github-api.js`.
🔧 Suggested Fix
  console.log("Fetching all PR comments to check for existing release commands...");
  const allComments = await listPRComments(owner, repo, prNumber);

for (const branch of targetBranches) {
const marker = &lt;!-- auto-release: ${branch} --&gt;;
const body = /release to ${branch}\n\n${marker};

try {
  // Check if this specific release command has already been posted
  const existingComment = allComments.find(comment =&gt; comment.body.includes(marker));

  if (existingComment) {
    console.log(
      `ℹ️  Release comment for ${branch} already exists. Skipping.`,
    );
    continue;
  }

  console.log(
    `Posting comment: &#34;/release to ${branch}&#34; on PR #${prNumber}...`,
  );
  await createPRComment(owner, repo, prNumber, body);
  console.log(`✅ Successfully posted release comment for ${branch}`);
} catch (error) {
  console.error(
    `❌ Failed to process release comment for ${branch}: ${error.message}`,
  );
}

}

Quality Issues (1)

Severity Location Issue
🟠 Error branch-suggestion/branch_suggestion.yml:125
The `add-pr-comment` job deletes `/tmp/branch_suggestion_results.json`, which is also required by the `post-release-commands` job. Since both jobs depend on `analyze-and-suggest`, they can run in parallel, creating a race condition where the file might be deleted before `post-release-commands` can use it, causing the workflow to fail.
💡 SuggestionThe `add-pr-comment` job should not be responsible for cleaning up a file it does not use. The cleanup of `/tmp/branch_suggestion_results.json` should be handled by its consumer (`post-release-commands`) or by a dedicated final cleanup job that runs after all other jobs have completed. The simplest fix is to remove the line `rm -f /tmp/branch_suggestion_results.json` from the `add-pr-comment` job and add it to the end of the `post-release-commands` job.

Powered by Visor from Probelabs

Last updated: 2026-05-14T17:29:58.199Z | Triggered by: pr_updated | Commit: 6b0bc76

💡 TIP: You can chat with Visor using /visor ask <your question>

@olamilekan000 olamilekan000 force-pushed the trigger-release-to-releas-branch-after-suggestion branch from 988fc3c to 3089c6e Compare May 14, 2026 17:09
probelabs[bot]
probelabs Bot previously approved these changes May 14, 2026
Copy link
Copy Markdown
Contributor

@probelabs probelabs Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR looks solid and correctly implements the automated release comments logic.

A few highlights:

  1. Idempotency: The use of <!-- auto-release: <branch> --> markers ensures we don't post duplicate comments if the workflow is re-run.
  2. Early Exits: Correctly skipping analysis when a PR is closed but not merged saves unnecessary API calls.
  3. Branch Filtering: Correctly filters out master and only targets required or recommended branches.

⚠️ Important Next Step for Adoption:
Because this is a reusable workflow, updating the on.pull_request.types here to include closed is only half the puzzle.
For this to actually trigger when a PR is merged in the tyk repository, you will also need to update the caller workflow in the tyk repo (.github/workflows/intelligent-branch-recomendations.yml) to include the closed event type:

on:
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
      - ready_for_review
      - closed # <--- This must be added in the tyk repo!

Great work on this!

@olamilekan000 olamilekan000 force-pushed the trigger-release-to-releas-branch-after-suggestion branch from 3089c6e to 2b10608 Compare May 14, 2026 17:24
@olamilekan000 olamilekan000 force-pushed the trigger-release-to-releas-branch-after-suggestion branch from 2b10608 to 6b0bc76 Compare May 14, 2026 17:28
@rafalgolarz rafalgolarz self-requested a review May 22, 2026 08:19
);

for (const branch of targetBranches) {
const marker = `<!-- auto-release: ${branch} -->`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @olamilekan000

If I understand the release bot correctly, it only accepts comments that match exactly:
https://github.com/TykTechnologies/github-actions/blob/main/.github/workflows/release-bot.yaml#L50

match(/^\/release to\s+([^\s]+)\s*$/i)

but the code here posts comments with an extra marker appended, so the final comment would be something like:

<!-- auto-release: release-5.8 -->

That won’t pass the release bot regex because the comment no longer ends after the branch name. We either need to make the release bot tolerate the marker, or avoid appending the marker to the command comment and detect duplicates another way.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a comment to show that it was automatically added. The bot should still pick it up

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, 🤔 I checked the call path again, and it looks like the marker is part of the actual comment body sent to GitHub:

const body = \/release to ${branch}\n\n${marker}`;`

and then:

await createPRComment(owner, repo, prNumber, body);

Since createPRComment sends that body as the issue comment, the release bot will receive the command plus the marker in the same comment. Without changing the release bot, could we post only the command itself and use exact command text for duplicate detection?

Are you able to test it? I might be wrong of course, but just want to be double sure :)

@@ -53,6 +53,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this may be a blocker for the intended hand-off to the release bot.

If these /release to <branch> comments are created with the default GITHUB_TOKEN, GitHub will generally not trigger another workflow from the resulting issue_comment.created event. The release bot depends on that event, so the comment may be created successfully but the release workflow may not start.

GitHub documents this behavior here:
https://docs.github.com/en/actions/how-tos/writing-workflows/choosing-when-your-workflow-runs/triggering-a-workflow

I think this needs to use a GitHub App token or PAT that is allowed to trigger the downstream workflow.

);
await createPRComment(owner, repo, prNumber, body);
console.log(`✅ Successfully posted release comment for ${branch}`);
} catch (error) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this fail the workflow if posting release commands fails?

Right now errors are logged per branch, but the function continues and can finish successfully even if all required release comments failed to post. That would make the merge look like the release hand-off happened when it did not.

Could we collect failures and throw at the end, at least for required branches?

// Collect all unique branches with priority 'required' or 'recommended'
const targetBranches = new Set();
for (const result of matchResults) {
for (const branchMatch of result.branches) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small robustness point: this assumes every match result has a branches array. If the matcher ever returns a partial/malformed result, this will throw before posting any release commands.

Maybe we could we guard this with something like:

for (const branchMatch of result.branches || [])

or an Array.isArray(result.branches) check?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants