> For the complete documentation index, see llms.txt.
Skip to main content

Check out Port for yourself ➜ 

Manage GitHub pull requests

Implement with AI

Send this guide to your coding agent.

Prerequisite: Install Port MCP

Open plan mode. Implement this Port guide in my org via MCP:

https://docs.port.io/guides/all/manage-pull-requests/

Goal: get the guide's core flow working end-to-end in my org; adapting it to fit my existing setup takes priority over matching the guide 1:1.

Plan:
1. Confirm MCP is connected, in the right org, with sufficient permissions.
2. Diff the guide's data model (blueprints, properties, relations, actions, agents, automations, integrations, secrets) against mine.
3. Propose adaptations for gaps, reusing existing blueprints/relations over guide-named duplicates.
4. Flag what needs a UI click, credential, or secret from me, testing MCP capability empirically before ruling anything out.
5. Stop on any blocker and give me options. Approving this plan authorizes the writes it lists; pause only for writes beyond what's listed.

Build:
- Extend blueprint schema additively when upserting; don't remove or overwrite existing properties, and treat type conflicts as a blocker, not an auto-fix.
- List any mock data in the plan, minimal and labeled mock; once approved, seed it without re-asking, and tell me what you seeded.
- For anything the guide writes downstream (e.g. a webhook target), use a real entity, not a mock.
- For pages/widgets, use the real page identifier from the app URL, not a guessed slug.
- When you hit a UI step confirmed (not assumed) unsupported via MCP, pause, give exact clicks, then resume via MCP.
- Validate and give links after each meaningful step (only a tool-returned URL, no guessed paths); don't proceed if the last run wasn't a success.

Done:
- Confirm the guide's expected output exists and runs in Port.
- Summarize adaptations, seeded data, what was mocked or skipped, remaining UI steps, and how to verify.

This guide demonstrates how to create a Port workflow that dispatches a GitHub Actions pipeline to manage GitHub pull requests directly from your catalog. You will be able to streamline your code review process by closing, merging, and approving pull requests without leaving Port.

Common use cases

  • Close pull requests with a single click.
  • Merge approved pull requests efficiently.
  • Approve pull requests as part of your review workflow.
  • Track PR operations and their results within Port.

Prerequisites

Set up data model

If you haven't installed the GitHub integration, you'll need to create a blueprint for GitHub pull requests and repositories. However, we highly recommend you install the GitHub integration to have these automatically set up for you.

Create the GitHub repository blueprint

  1. Go to your builder page.

  2. Click on + Blueprint.

  3. Click on the {...} button in the top right corner, and choose Edit JSON.

  4. Add this JSON schema:

    GitHub repository blueprint (click to expand)
    {
    "identifier": "githubRepository",
    "title": "Repository",
    "icon": "Github",
    "ownership": {
    "type": "Direct"
    },
    "schema": {
    "properties": {
    "readme": {
    "title": "README",
    "type": "string",
    "format": "markdown"
    },
    "url": {
    "icon": "DefaultProperty",
    "title": "Repository URL",
    "type": "string",
    "format": "url"
    },
    "defaultBranch": {
    "title": "Default branch",
    "type": "string"
    },
    "last_contributor": {
    "title": "Last contributor",
    "icon": "TwoUsers",
    "type": "string",
    "format": "user"
    },
    "last_push": {
    "icon": "GitPullRequest",
    "title": "Last push",
    "description": "Last commit to the main branch",
    "type": "string",
    "format": "date-time"
    },
    "require_code_owner_review": {
    "title": "Require code owner review",
    "type": "boolean",
    "icon": "DefaultProperty",
    "description": "Requires review from code owners before a pull request can be merged"
    },
    "require_approval_count": {
    "title": "Require approvals",
    "type": "number",
    "icon": "DefaultProperty",
    "description": "The number of approvals required before merging a pull request"
    }
    },
    "required": []
    },
    "mirrorProperties": {
    "snyk_target_id": {
    "title": "snyk_target_id",
    "path": "snyk_target.$identifier"
    }
    },
    "calculationProperties": {},
    "aggregationProperties": {},
    "relations": {}
    }
  5. Click on the Save button.

Create the GitHub pull request blueprint

  1. Go to your builder page.

  2. Click on + Blueprint.

  3. Click on the {...} button in the top right corner, and choose Edit JSON.

  4. Add this JSON schema:

    GitHub pull request blueprint (click to expand)
    {
    "identifier": "githubPullRequest",
    "title": "Pull Request",
    "icon": "Github",
    "schema": {
    "properties": {
    "creator": {
    "title": "Creator",
    "type": "string"
    },
    "assignees": {
    "title": "Assignees",
    "type": "array"
    },
    "reviewers": {
    "title": "Reviewers",
    "type": "array"
    },
    "status": {
    "title": "Status",
    "type": "string",
    "enum": ["merged", "open", "closed"],
    "enumColors": {
    "merged": "purple",
    "open": "green",
    "closed": "red"
    }
    },
    "closedAt": {
    "title": "Closed At",
    "type": "string",
    "format": "date-time"
    },
    "updatedAt": {
    "title": "Updated At",
    "type": "string",
    "format": "date-time"
    },
    "mergedAt": {
    "title": "Merged At",
    "type": "string",
    "format": "date-time"
    },
    "createdAt": {
    "title": "Created At",
    "type": "string",
    "format": "date-time"
    },
    "link": {
    "format": "url",
    "type": "string"
    },
    "leadTimeHours": {
    "title": "Lead Time in hours",
    "type": "number"
    }
    },
    "required": []
    },
    "mirrorProperties": {},
    "calculationProperties": {
    "days_old": {
    "title": "Days Old",
    "icon": "DefaultProperty",
    "calculation": "(now / 86400) - (.properties.createdAt | capture(\"(?<date>\\\\d{4}-\\\\d{2}-\\\\d{2})\") | .date | strptime(\"%Y-%m-%d\") | mktime / 86400) | floor",
    "type": "number"
    }
    },
    "relations": {
    "repository": {
    "title": "Repository",
    "target": "githubRepository",
    "required": false,
    "many": false
    }
    }
    }
  5. Click on the Save button.

Set up the backend

The workflow dispatches a GitHub Actions pipeline that performs the requested operation against the GitHub API. First, add the secret the pipeline needs, then create the pipeline itself.

Add GitHub secrets

In your GitHub repository, go to Settings > Secrets and add the following secret:

Create the GitHub workflow

Create a workflow file under .github/workflows/manage-pr.yml with the following content:

GitHub workflow (click to expand)
manage-pr.yml
name: Manage Pull Request

on:
workflow_dispatch:
inputs:
action:
required: true
description: "The action to perform on the pull request (close, merge, or approve)"
type: string
pr_link:
required: true
description: "The URL of the pull request to manage"
type: string

jobs:
manage-pr:
runs-on: ubuntu-latest

steps:
- name: Extract repository and PR number
id: extract_info
run: |
link="${{ inputs.pr_link }}"
repo_info=$(echo "$link" | sed 's|https://github.com/||' | awk -F'/' '{print $1 "/" $2}')
pr_number=$(echo "$link" | awk -F'/' '{print $NF}')

echo "REPO_INFO=$repo_info" >> $GITHUB_ENV
echo "PR_NUMBER=$pr_number" >> $GITHUB_ENV

- name: Determine action
run: |
action="${{ github.event.inputs.action }}"
repo_info="${{ env.REPO_INFO }}"
pr_number="${{ env.PR_NUMBER }}"

result=""
result_message=""

if [ -n "$repo_info" ] && [ -n "$pr_number" ]; then
if [ "$action" == "close" ]; then
result=$(curl -s -o /dev/null -w "%{http_code}" \
-X PATCH \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$repo_info/pulls/$pr_number" \
-d '{"state": "closed"}')
elif [ "$action" == "merge" ]; then
result=$(curl -s -o /dev/null -w "%{http_code}" \
-X PUT \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$repo_info/pulls/$pr_number/merge")
elif [ "$action" == "approve" ]; then
result=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$repo_info/pulls/$pr_number/reviews" \
-d '{"event": "APPROVE"}')
else
result_message="Invalid action specified. Expected 'close', 'approve' or 'merge'."
echo "$result_message"
exit 1
fi
else
result_message="Failed to extract repository and PR number from the URL."
echo "$result_message"
exit 1
fi

echo "HTTP status for $action: $result"

if [ "$result" -eq 200 ]; then
echo "PR $action completed successfully"
else
echo "PR $action failed. HTTP status: $result"
exit 1
fi
Customize your workflow

You can customize this pipeline to include additional PR management operations or integrate with other tools in your development workflow. Refer to the GitHub API documentation for more available operations.

Build the workflow

The workflow has three nodes:

  1. Trigger - a self-service trigger that lets users select a pull request entity and the action to perform.
  2. Fetch PR - calls Port's catalog API to retrieve the pull request entity's link property.
  3. Manage PR - dispatches the manage-pr.yml GitHub Actions pipeline through the GitHub integration action, passing the action and the PR link.

To create the workflow:

  1. Go to the Workflows page in Port.
  2. Click on the + Workflow button in the top-right corner.
  3. In the Name field, enter Manage Pull Request, then click Confirm.
  4. On the editor page, click the see workflow JSON button (the code icon) to open the JSON editor.
  5. Copy and paste the workflow JSON below to replace the example workflow:
Manage GitHub PR workflow JSON (click to expand)
{
"identifier": "manage_github_pull_request",
"title": "Manage Pull Request",
"icon": "Github",
"description": "Close, merge, or approve a GitHub pull request",
"allowAnyoneToViewRuns": true,
"nodes": [
{
"identifier": "trigger",
"title": "Manage a GitHub PR",
"config": {
"type": "SELF_SERVE_TRIGGER",
"userInputs": {
"properties": {
"pullRequest": {
"title": "Pull Request",
"description": "Select the pull request to manage",
"type": "string",
"format": "entity",
"blueprint": "githubPullRequest"
},
"action": {
"title": "Action",
"description": "The action to perform on the pull request",
"icon": "Git",
"type": "string",
"enum": ["close", "merge", "approve"],
"enumColors": {
"close": "lightGray",
"merge": "green",
"approve": "blue"
}
}
},
"required": ["pullRequest", "action"],
"order": ["pullRequest", "action"]
},
"contexts": [
{
"on": "ENTITY",
"userInput": "pullRequest"
}
]
}
},
{
"identifier": "fetch_pr",
"title": "Fetch pull request",
"config": {
"type": "WEBHOOK",
"url": "https://api.port.io/v1/blueprints/githubPullRequest/entities/{{ .outputs.trigger.pullRequest }}",
"method": "GET",
"synchronized": true
},
"variables": {
"link": "{{ .result.response.data.entity.properties.link }}"
}
},
{
"identifier": "manage_pr",
"title": "Manage pull request",
"config": {
"type": "INTEGRATION_ACTION",
"installationId": "<YOUR_GITHUB_OCEAN_INTEGRATION_ID>",
"integrationProvider": "github-ocean",
"integrationInvocationType": "dispatch_workflow",
"integrationActionExecutionProperties": {
"org": "<GITHUB-ORG>",
"repo": "<GITHUB-REPO-NAME>",
"workflow": "manage-pr.yml",
"workflowInputs": {
"action": "{{ .outputs.trigger.action }}",
"pr_link": "{{ .outputs.fetch_pr.link }}"
},
"reportWorkflowStatus": true
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "fetch_pr"
},
{
"sourceIdentifier": "fetch_pr",
"targetIdentifier": "manage_pr"
}
]
}
  1. Click Save to save the workflow.
Replace placeholders

Replace YOUR_GITHUB_OCEAN_INTEGRATION_ID, YOUR_GITHUB_ORG, and YOUR_WORKFLOW_REPO with your GitHub Ocean integration ID, organization name, and the repository where manage-pr.yaml lives. You can find the integration ID on the Data sources page in Port.

Let's test it!

You can trigger the workflow in two ways:

  • From the Self-service page: Go to the Self-service page, find Manage a GitHub PR, click it, and select a pull request from the dropdown.
  • From an entity: In the githubPullRequest catalog page, click the bolt (⚡) menu on any PR row and select Manage a GitHub PR, and the PR is pre-filled automatically.

Then:

  1. Choose the action you want to perform (close, merge, or approve).
  2. Click Execute.
  3. Open the workflow runs tab and confirm the run completed successfully.

Congrats! You can now manage GitHub pull requests directly from Port with close, merge, and approve actions.