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

Check out Port for yourself ➜ 

Roll back an ArgoCD deployment via GitHub Actions

Implement with AI

Send this guide to your coding agent.

Prerequisite: Install Port MCP

Open plan mode if your tool supports it; otherwise present the plan below filled in and wait for my approval. Implement this Port guide in my org via MCP:

https://docs.port.io/guides/all/rollback-argocd-deployment

Read the raw markdown version at https://docs.port.io/guides/all/rollback-argocd-deployment.md - it contains every tab and code block without page markup.

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. If the guide offers alternative implementation paths (tabs), pick the one matching my installed integrations and tools, confirm it with me, and implement only that path.
3. Diff the guide's data model (blueprints, properties, relations, workflows, actions, agents, automations, integrations, webhook data sources, secrets) against mine.
4. Propose adaptations for gaps, reusing existing blueprints/relations over guide-named duplicates.
5. Flag what needs a UI click, credential, or secret from me, testing MCP capability empirically before ruling anything out. If the guide has a "Set up via API" section, use it for anything MCP can't do before treating a step as UI-only.
6. 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.
- Never print secret values into the chat or logs; ask me to set them in Port, or write them via the secrets API without echoing them back.
- 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 and not covered by the guide's API sections, 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:
- Run the guide's "Let's test it" steps where possible (e.g. execute a workflow test run) and confirm the expected output exists in Port.
- Summarize adaptations, seeded data, what was mocked or skipped, remaining UI steps, and how to verify.

In this guide, we will create a Port workflow that dispatches a GitHub Actions workflow to perform either a deployment or rollback operation using ArgoCD.

Open Beta

Port workflows are currently in open beta and available to all users. Workflows may undergo changes without prior notice.

Workflow triggered from a service entity, fetching the image entity, then dispatching the GitHub rollback backend
Updating Environments

It's important to note that Deployment and Rollback operations essentially perform the same operation, with the difference being that Rollback occurs in the production environment and requires manual approval.

Both operations involve updating the deployment manifest with a new container image and creating a GitHub pull request (PR) for it. The workflow can optionally merge the PR when enabled.

Prerequisites

  1. Port's GitHub Ocean integration is installed.
  2. This guide assumes the presence of a Service and Image blueprint representing your repository where ArgoCD lives and your container image.
  3. A repository to contain your ArgoCD deployment manifest and workflow resources i.e. the GitHub Actions workflow file.

Below you can find the JSON for the Service and Image blueprints required for the guide:

Service blueprint (click to expand)
{
"identifier": "service",
"title": "Service",
"icon": "Github",
"schema": {
"properties": {
"readme": {
"title": "README",
"type": "string",
"format": "markdown",
"icon": "Book"
},
"url": {
"title": "URL",
"format": "url",
"type": "string",
"icon": "Link"
},
"language": {
"icon": "Git",
"type": "string",
"title": "Language",
"enum": [
"GO",
"Python",
"Node",
"React"
],
"enumColors": {
"GO": "red",
"Python": "green",
"Node": "blue",
"React": "yellow"
}
},
"slack": {
"icon": "Slack",
"type": "string",
"title": "Slack",
"format": "url"
},
"code_owners": {
"title": "Code owners",
"description": "This service's code owners",
"type": "string",
"icon": "TwoUsers"
},
"type": {
"title": "Type",
"description": "This service's type",
"type": "string",
"enum": [
"Backend",
"Frontend",
"Library"
],
"enumColors": {
"Backend": "purple",
"Frontend": "pink",
"Library": "green"
},
"icon": "DefaultProperty"
},
"lifecycle": {
"title": "Lifecycle",
"type": "string",
"enum": [
"Production",
"Experimental",
"Deprecated"
],
"enumColors": {
"Production": "green",
"Experimental": "yellow",
"Deprecated": "red"
},
"icon": "DefaultProperty"
},
"locked_in_prod": {
"icon": "DefaultProperty",
"title": "Locked in Prod",
"type": "boolean",
"default": false
},
"locked_reason_prod": {
"icon": "DefaultProperty",
"title": "Locked Reason Prod",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Image blueprint (click to expand)
{
"identifier": "image",
"description": "This blueprint represents an image",
"title": "Image",
"icon": "AWS",
"schema": {
"properties": {
"registryId": {
"type": "string",
"title": "Registry ID",
"description": "The ID of the registry",
"icon": "DefaultProperty"
},
"digest": {
"type": "string",
"title": "Image Digest",
"description": "SHA256 digest of image manifest",
"icon": "DefaultProperty"
},
"tags": {
"type": "array",
"title": "Image Tags",
"description": "List of tags for the image",
"icon": "DefaultProperty"
},
"pushedAt": {
"type": "string",
"title": "Pushed At",
"description": "Date and time the image was pushed to the repository",
"format": "date-time",
"icon": "DefaultProperty"
},
"lastRecordedPullTime": {
"type": "string",
"title": "Last Recorded Pull Time",
"description": "Date and time the image was last pulled",
"format": "date-time",
"icon": "DefaultProperty"
},
"triggeredBy": {
"type": "string",
"icon": "TwoUsers",
"title": "Triggered By",
"description": "The user who triggered the run"
},
"commitHash": {
"type": "string",
"title": "Commit Hash",
"icon": "DefaultProperty"
},
"pullRequestId": {
"type": "string",
"icon": "Git",
"title": "Pull Request ID"
},
"workflowId": {
"type": "string",
"title": "Workflow ID",
"icon": "DefaultProperty"
},
"image_branch": {
"title": "Image branch",
"type": "string",
"description": "The git branch associated with the repository used to build the Image"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {}
}
Ingest Images

If you do not have the images ingested already, we recommend using our AWS ECR script, Google Container Registry script, JFrog build script or GitHub packages script to sync data to your catalog

Create the GitHub workflow backend

Follow these steps to get started:

  1. Create the following GitHub Action secret:
    • MY_GITHUB_TOKEN - a Classic Personal Access Token with the repo scope and the following permissions: pull_requests:write (to create PR) and contents:write (to merge PR)

  1. Create a workflow file under .github/workflows/rollback.yaml with the following content:
GitHub workflow script (click to expand)
Variable replacement
  • <DEPLOYMENT-MANIFEST-PATH> - Path to the ArgoCD deployment manifest such as app/deployment.yaml.
  • <IMAGE-PROPERTY-PATH> - Path to where the deployment image is specified in the deployment manifest such as spec.template.spec.containers[0].image.
rollback.yaml
name: Rollback ArgoCD Deployment Image

on:
workflow_dispatch:
inputs:
image:
description: The new image to use for the rollback
required: true
type: string
auto_merge:
description: Whether the created PR should be merged automatically
required: true
type: boolean

jobs:
rollback-deployment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Create PR
id: create-pr
uses: fjogeleit/yaml-update-action@main
with:
valueFile: "<DEPLOYMENT-MANIFEST-PATH>" ## replace value
propertyPath: "<IMAGE-PROPERTY-PATH>" ## replace value
value: "${{ github.event.inputs.image }}"
commitChange: true
token: ${{ secrets.MY_GITHUB_TOKEN }}
targetBranch: main
masterBranchName: main
createPR: true
branch: deployment/${{ github.run_id }}
message: "Update deployment image to ${{ github.event.inputs.image }}"

- name: Merge Pull Request
if: ${{ github.event.inputs.auto_merge == 'true' && steps.create-pr.outcome == 'success' }}
env:
GH_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }}
PR_URL: ${{ fromJson(steps.create-pr.outputs.pull_request).url }}
run: |
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X PUT \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GH_TOKEN" \
"$PR_URL/merge")

echo "HTTP Status: $HTTP_STATUS"

if [ $HTTP_STATUS -eq 200 ]; then
echo "Pull request merged successfully."
else
echo "Failed to merge PR. HTTP Status: $HTTP_STATUS"
exit 1
fi
Workflow run status is reported automatically

The Port workflow dispatches this file with reportWorkflowStatus: true, so the node's success or failure is reflected on the workflow run automatically. No port-labs/port-github-action status steps or PORT_CLIENT_ID/PORT_CLIENT_SECRET secrets are needed inside this backend.

Build the workflow

Follow these steps to get started:

  1. Go to the Workflows page in Port.

  2. Click on the + Workflow button in the top-right corner.

  3. Click on the {...} button in the top right corner.

  4. Copy and paste the workflow JSON below into the editor to replace the example workflow:

Port Workflow: Rollback Deployment (click to expand)
Replace the variables
  • <YOUR_GITHUB_OCEAN_INTEGRATION_ID> - your GitHub Ocean integration installation ID.
  • <GITHUB-ORG> - your GitHub organization or user name.
  • <GITHUB-REPO-NAME> - your GitHub repository name.
{
"identifier": "rollback_argocd_deployment",
"title": "Rollback ArgoCD Deployment",
"icon": "Argo",
"description": "Roll back an ArgoCD-managed service by updating its deployment manifest image and opening a pull request",
"allowAnyoneToViewRuns": true,
"nodes": [
{
"identifier": "trigger",
"title": "Rollback Deployment",
"config": {
"type": "SELF_SERVE_TRIGGER",
"contexts": [
{
"on": "ENTITY",
"userInput": "service"
}
],
"userInputs": {
"properties": {
"service": {
"type": "string",
"format": "entity",
"blueprint": "service",
"title": "Service"
},
"image": {
"type": "string",
"format": "entity",
"blueprint": "image",
"title": "Image",
"description": "The image to roll back to"
},
"auto_merge": {
"type": "boolean",
"title": "Auto Merge",
"default": false,
"description": "Automatically merge the PR after the workflow completes"
}
},
"required": [
"service",
"image"
],
"order": [
"service",
"image",
"auto_merge"
]
}
}
},
{
"identifier": "fetch_image",
"title": "Fetch Image Entity",
"config": {
"type": "WEBHOOK",
"url": "https://api.port.io/v1/blueprints/image/entities/search",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"query": {
"combinator": "and",
"rules": [
{
"property": "$identifier",
"operator": "=",
"value": "{{ .outputs.trigger.image }}"
}
]
}
}
},
"variables": {
"entity": "{{ .result.response.data.entities[0] }}"
}
},
{
"identifier": "trigger_rollback",
"title": "Trigger GitHub Rollback Workflow",
"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": "rollback.yaml",
"workflowInputs": {
"auto_merge": "{{ .outputs.trigger.auto_merge | tostring }}",
"image": "{{ .outputs.fetch_image.entity.title }}"
},
"reportWorkflowStatus": true
}
}
}
],
"connections": [
{
"sourceIdentifier": "trigger",
"targetIdentifier": "fetch_image"
},
{
"sourceIdentifier": "fetch_image",
"targetIdentifier": "trigger_rollback"
}
]
}

  1. Click Save to save the workflow.
Self-hosted GitHub Ocean installations

If your GitHub Ocean integration is self-hosted (Helm or Docker), actions processing and reportWorkflowStatus require extra setup. See Enable actions processing for self-hosted installations.

Match the entity relation

The service input's ENTITY context assumes your GitHub Ocean setup exposes a service blueprint on repository entities. If your default relation key differs (for example repository or github_repository), verify it against your own blueprints before publishing the workflow.

  1. Trigger the workflow from the bolt (⚡) menu of a Service entity, or from the self-service page of your Port application.

You should now be able to see a Github pull request created and merged for the argocd deployment.

Merged PR updating deployment.yaml container image version

More relevant guides and examples