Skip to main content

Change Deployment Replica Count

In this guide, we will create a self-service action in Port that executes a GitHub workflow to change the number of replica counts in a kubernetes deployment. The workflow involves updating the deployment manifest with the new replica count(s) and creating a Github pull request (PR) for it. The workflow can optionally merge the PR when enabled.

Prerequisites​

  1. Install Port's GitHub app by clicking here
  2. This guide assumes the presence of a Service blueprint representing the repository where ArgoCD or Kubernetes workload lives
  3. A repository to contain your deployment manifest and action resources i.e. the github workflow file

Below you can find the JSON for the Service blueprint 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": {}
}

Create Github workflow​

Follow these steps to get started:

  1. Create the following GitHub Action secrets:
    • PORT_CLIENT_ID - Port Client ID learn more
    • PORT_CLIENT_SECRET - Port Client Secret learn more
    • 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 Port action in the self-service page on the Service blueprint with the following JSON definition:
Port Action: Change Replica Count
tip
  • <GITHUB-ORG> - your GitHub organization or user name.
  • <GITHUB-REPO-NAME> - your GitHub repository name.
{
"identifier": "service_change_replica_count",
"title": "Change Replica Count",
"icon": "GithubActions",
"trigger": {
"type": "self-service",
"operation": "DAY-2",
"userInputs": {
"properties": {
"replica_count": {
"icon": "DefaultProperty",
"title": "Number of Replicas",
"type": "number"
},
"auto_merge": {
"title": "Auto Merge",
"type": "boolean",
"default": false,
"description": "Whether the created PR should be merged or not"
}
},
"required": [
"replica_count"
],
"order": [
"replica_count",
"auto_merge"
]
},
"blueprintIdentifier": "service"
},
"invocationMethod": {
"type": "GITHUB",
"org": "<GITHUB-ORG>",
"repo": "<GITHUB-REPO-NAME>",
"workflow": "change-replica-count.yaml",
"workflowInputs": {
"{{if (.inputs | has(\"ref\")) then \"ref\" else null end}}": "{{.inputs.\"ref\"}}",
"{{if (.inputs | has(\"replica_count\")) then \"replica_count\" else null end}}": "{{.inputs.\"replica_count\"}}",
"{{if (.inputs | has(\"auto_merge\")) then \"auto_merge\" else null end}}": "{{.inputs.\"auto_merge\"}}",
"port_payload": {
"action": "{{ .action.identifier[(\"service_\" | length):] }}",
"resourceType": "run",
"status": "TRIGGERED",
"trigger": "{{ .trigger | {by, origin, at} }}",
"context": {
"entity": "{{.entity.identifier}}",
"blueprint": "{{.action.blueprint}}",
"runId": "{{.run.id}}"
},
"payload": {
"entity": "{{ (if .entity == {} then null else .entity end) }}",
"action": {
"invocationMethod": {
"type": "GITHUB",
"org": "<GITHUB-ORG>",
"repo": "<GITHUB-REPO-NAME>",
"workflow": "change-replica-count.yaml",
"omitUserInputs": false,
"omitPayload": false,
"reportWorkflowStatus": true
},
"trigger": "{{.trigger.operation}}"
},
"properties": {
"{{if (.inputs | has(\"replica_count\")) then \"replica_count\" else null end}}": "{{.inputs.\"replica_count\"}}",
"{{if (.inputs | has(\"auto_merge\")) then \"auto_merge\" else null end}}": "{{.inputs.\"auto_merge\"}}"
},
"censoredProperties": "{{.action.encryptedProperties}}"
}
}
},
"reportWorkflowStatus": true
},
"requiredApproval": false,
"publish": true
}

  1. Create a workflow file under .github/workflows/change-replica-count.yml with the following content:
GitHub workflow script
Variable replacement
  • <DEPLOYMENT-MANIFEST-PATH> - Path to the ArgoCD or K8s deployment manifest such as app/deployment.yaml.
  • <REPLICA-PROPERTY-PATH> - Path to where the deployment replica count is specified in the deployment manifest such as spec.replicas.
change-replica-count.yml
name: Change Replica Count

on:
workflow_dispatch:
inputs:
replica_count:
description: The new replica count for the deployment
required: true
type: string
auto_merge:
description: Whether the created PR should be merged automatically
required: true
type: boolean
port_payload:
required: true
description: >-
Port's payload, including details for who triggered the action and
general context (blueprint, run id, etc...)
jobs:
change-replica-count:
runs-on: ubuntu-latest
steps:
- name: Inform execution of request to change replica count
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{fromJson(github.event.inputs.port_payload).context.runId}}
logMessage: "About to change replica count in deployment manifest..."

- uses: actions/checkout@v3
- name: Create PR
id: create-pr
uses: fjogeleit/yaml-update-action@main
with:
valueFile: '<DEPLOYMENT-MANIFEST-PATH>' ## replace value
propertyPath: '<REPLICA-PROPERTY-PATH>' ## replace value
value: "!!int '${{ fromJson(github.event.inputs.replica_count) }}'" ## using the yaml tag (!!int 'X') to convert the string to int
commitChange: true
token: ${{ secrets.MY_GITHUB_TOKEN }}
targetBranch: main
masterBranchName: main
createPR: true
branch: deployment/${{ fromJson(github.event.inputs.port_payload).context.runId }}
message: 'Update deployment replica to ${{ github.event.inputs.replica_count }}'

- name: Inform Port about pull request creation status - Success
if: steps.create-pr.outcome == 'success'
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{ fromJson(github.event.inputs.port_payload).context.runId }}
logMessage: |
'The creation of PR was successful: ${{fromJson(steps.create-pr.outputs.pull_request).html_url}}'
link: '["${{fromJson(steps.create-pr.outputs.pull_request).html_url}}"]'

- name: Inform Port about pull request creation status - Failure
if: steps.create-pr.outcome != 'success'
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{ fromJson(github.event.inputs.port_payload).context.runId }}
logMessage: |
The creation of PR was not successful.

- 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."
echo "merge_status=successful" >> $GITHUB_ENV
else
echo "Failed to merge PR. HTTP Status: $HTTP_STATUS"
echo "merge_status=unsuccessful" >> $GITHUB_ENV
fi

- name: Inform completion of replica update operation to Port
if: ${{ github.event.inputs.auto_merge == 'true' }}
uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
baseUrl: https://api.getport.io
operation: PATCH_RUN
runId: ${{fromJson(github.event.inputs.port_payload).context.runId}}
logMessage: 'Pull request merge was ${{ env.merge_status }}'


  1. Trigger the action 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 deployment: