Configuring the GitOps Manifest Updater Frontend Plugin#
This guide covers the configuration options available for the GitOps Manifest Updater frontend plugin.
Example Configuration for GitHub based SCM#
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: update-kubernetes-manifest
title: Update Kubernetes Manifest
labels:
target: component
description: A template to update a claim manifest in Git based on the registered OpenAPI Schema of the XRD
spec:
owner: user:guest
type: service
parameters:
- title: Entity Selection
required:
- entity
properties:
entity:
title: Entity
type: string
description: Select the entity to update
ui:field: EntityPicker
ui:options:
catalogFilter:
- kind: Component
sourceFileUrl:
title: Source File URL
type: string
description: Override the source file URL (optional - only needed if entity doesn't have terasky.backstage.io/source-file-url annotation)
- title: GitOps Manifest Updater
required:
- gitOpsManifestUpdater
properties:
gitOpsManifestUpdater:
title: GitOps Manifest Updater
type: object
ui:field: GitOpsManifestUpdater
steps:
- id: get-entity
name: Get Entity
action: catalog:fetch
input:
entityRef: ${{ parameters.entity }}
- id: get-annotation-url
name: Get Annotation URL
action: roadiehq:utils:jsonata
input:
data:
annotations: ${{ steps['get-entity'].output.entity.metadata.annotations }}
expression: |
annotations."terasky.backstage.io/source-file-url"
- id: resolve-url
name: Resolve URL
action: roadiehq:utils:jsonata
input:
data:
sourceFileUrl: ${{ parameters.sourceFileUrl }}
annotationUrl: ${{ steps['get-annotation-url'].output.result }}
expression: |
$exists(sourceFileUrl) ? sourceFileUrl : annotationUrl
- id: validate-url
name: Validate URL
action: roadiehq:utils:jsonata
input:
data: ${{ steps['resolve-url'].output.result }}
expression: |
$string($) ? $ : $error("No source URL provided. Please either add the terasky.backstage.io/source-file-url annotation to the entity or provide a sourceFileUrl parameter")
- id: get-filepath
name: Get File Path
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
$join($filter($split($, "/"), function($v, $i) { $i >= 7}), "/")
- id: fetch-base
name: Fetch Current Manifest
action: fetch:plain:file
input:
url: ${{ steps['validate-url'].output.result }}
targetPath: ${{ steps['get-filepath'].output.result }}
- id: serialize-patch
name: Evaluate Changes
action: roadiehq:utils:serialize:yaml
input:
data:
spec: ${{ parameters.gitOpsManifestUpdater }}
- id: merge-patch
name: Merge Changes
action: roadiehq:utils:merge
input:
path: ${{ steps['get-filepath'].output.result }}
content: ${{ steps['serialize-patch'].output.serialized }}
- id: read-file
name: Read File
action: roadiehq:utils:fs:parse
input:
path: ${{ steps['get-filepath'].output.result }}
- id: parse-url
name: Parse URL for PR
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
{
"owner": $split($, "/")[3],
"repo": $split($, "/")[4],
"branch": $split($, "/")[6]
}
- id: format-branch-name
name: Format Branch Name
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
"backstage-sourced-update-" & $join($filter($split($, "/"), function($v, $i) { $i >= 7}), "-")
- id: create-pull-request
name: create-pull-request
action: publish:github:pull-request
input:
repoUrl: ${{ 'github.com?owner=' + steps['parse-url'].output.result.owner + '&repo=' + steps['parse-url'].output.result.repo }}
branchName: ${{ steps['format-branch-name'].output.result }}
title: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
description: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
targetBranchName: ${{ steps['parse-url'].output.result.branch }}
output:
links:
- title: Pull Request
url: ${{ steps['create-pull-request'].output.remoteUrl }}
- title: Download YAML Manifest
url: data:application/yaml;charset=utf-8,${{ steps['read-file'].output.content }}
Example Configuration for Gitlab based SCM#
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: update-kubernetes-manifest-gitlab
title: Update Kubernetes Manifest From Gitlab
labels:
target: component
description: A template to update a claim manifest in Git based on the registered OpenAPI Schema of the XRD
spec:
owner: user:guest
type: service
parameters:
- title: Entity Selection
required:
- entity
properties:
entity:
title: Entity
type: string
description: Select the entity to update
ui:field: EntityPicker
ui:options:
catalogFilter:
- kind: Component
sourceFileUrl:
title: Source File URL
type: string
description: Override the source file URL (optional - only needed if entity doesn't have terasky.backstage.io/source-file-url annotation)
- title: GitOps Manifest Updater
required:
- gitOpsManifestUpdater
properties:
gitOpsManifestUpdater:
title: GitOps Manifest Updater
type: object
ui:field: GitOpsManifestUpdater
steps:
- id: get-entity
name: Get Entity
action: catalog:fetch
input:
entityRef: ${{ parameters.entity }}
- id: get-annotation-url
name: Get Annotation URL
action: roadiehq:utils:jsonata
input:
data:
annotations: ${{ steps['get-entity'].output.entity.metadata.annotations }}
expression: |
annotations."terasky.backstage.io/source-file-url"
- id: resolve-url
name: Resolve URL
action: roadiehq:utils:jsonata
input:
data:
sourceFileUrl: ${{ parameters.sourceFileUrl }}
annotationUrl: ${{ steps['get-annotation-url'].output.result }}
expression: |
$exists(sourceFileUrl) ? sourceFileUrl : annotationUrl
- id: validate-url
name: Validate URL
action: roadiehq:utils:jsonata
input:
data: ${{ steps['resolve-url'].output.result }}
expression: |
$string($) ? $ : $error("No source URL provided. Please either add the terasky.backstage.io/source-file-url annotation to the entity or provide a sourceFileUrl parameter")
- id: get-filepath
name: Get File Path
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
$join($filter($split($, "/"), function($v, $i) { $i >= 8}), "/")
- id: fetch-base
name: Fetch Current Manifest
action: fetch:plain:file
input:
url: ${{ steps['validate-url'].output.result }}
targetPath: ${{ steps['get-filepath'].output.result }}
- id: serialize-patch
name: Evaluate Changes
action: roadiehq:utils:serialize:yaml
input:
data:
spec: ${{ parameters.gitOpsManifestUpdater }}
- id: merge-patch
name: Merge Changes
action: roadiehq:utils:merge
input:
path: ${{ steps['get-filepath'].output.result }}
content: ${{ steps['serialize-patch'].output.serialized }}
- id: read-file
name: Read File
action: roadiehq:utils:fs:parse
input:
path: ${{ steps['get-filepath'].output.result }}
- id: parse-url
name: Parse URL for PR
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
{
"owner": $split($, "/")[3],
"repo": $split($, "/")[4],
"branch": $split($, "/")[7]
}
- id: format-branch-name
name: Format Branch Name
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
"backstage-sourced-update-" & $join($filter($split($, "/"), function($v, $i) { $i >= 8}), "-")
- id: create-merge-request
name: create-merge-request
action: publish:gitlab:merge-request
input:
repoUrl: ${{ 'gitlab.com?owner=' + steps['parse-url'].output.result.owner + '&repo=' + steps['parse-url'].output.result.repo }}
branchName: ${{ steps['format-branch-name'].output.result }}
title: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
description: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
targetBranchName: ${{ steps['parse-url'].output.result.branch }}
output:
links:
- title: Merge Request
url: ${{ steps['create-merge-request'].output.mergeRequestUrl }}
- title: Download YAML Manifest
url: data:application/yaml;charset=utf-8,${{ steps['read-file'].output.content }}
Component Configuration#
Integration Examples#
Basic Integration#
Advanced Integration#
<ScaffolderFieldExtensions>
<GitOpsManifestUpdaterExtension
defaultBranch="develop"
defaultPath="k8s/"
schemaValidator={customValidator}
pullRequestCreator={customPRCreator}
/>
</ScaffolderFieldExtensions>
Template Examples#
Kubernetes Resource Update#
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: update-kubernetes-manifest
title: Update Kubernetes Manifest
labels:
target: component
description: A template to update a claim manifest in Git based on the registered OpenAPI Schema of the XRD
spec:
owner: user:guest
type: service
parameters:
- title: Entity Selection
required:
- entity
properties:
entity:
title: Entity
type: string
description: Select the entity to update
ui:field: EntityPicker
ui:options:
catalogFilter:
- kind: Component
sourceFileUrl:
title: Source File URL
type: string
description: Override the source file URL (optional - only needed if entity doesn't have terasky.backstage.io/source-file-url annotation)
- title: GitOps Manifest Updater
required:
- gitOpsManifestUpdater
properties:
gitOpsManifestUpdater:
title: GitOps Manifest Updater
type: object
ui:field: GitOpsManifestUpdater
steps:
- id: get-entity
name: Get Entity
action: catalog:fetch
input:
entityRef: ${{ parameters.entity }}
- id: get-annotation-url
name: Get Annotation URL
action: roadiehq:utils:jsonata
input:
data:
annotations: ${{ steps['get-entity'].output.entity.metadata.annotations }}
expression: |
annotations."terasky.backstage.io/source-file-url"
- id: resolve-url
name: Resolve URL
action: roadiehq:utils:jsonata
input:
data:
sourceFileUrl: ${{ parameters.sourceFileUrl }}
annotationUrl: ${{ steps['get-annotation-url'].output.result }}
expression: |
$exists(sourceFileUrl) ? sourceFileUrl : annotationUrl
- id: validate-url
name: Validate URL
action: roadiehq:utils:jsonata
input:
data: ${{ steps['resolve-url'].output.result }}
expression: |
$string($) ? $ : $error("No source URL provided. Please either add the terasky.backstage.io/source-file-url annotation to the entity or provide a sourceFileUrl parameter")
- id: get-filepath
name: Get File Path
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
$join($filter($split($, "/"), function($v, $i) { $i >= 7}), "/")
- id: fetch-base
name: Fetch Current Manifest
action: fetch:plain:file
input:
url: ${{ steps['validate-url'].output.result }}
targetPath: ${{ steps['get-filepath'].output.result }}
- id: serialize-patch
name: Evaluate Changes
action: roadiehq:utils:serialize:yaml
input:
data:
spec: ${{ parameters.gitOpsManifestUpdater }}
- id: merge-patch
name: Merge Changes
action: roadiehq:utils:merge
input:
path: ${{ steps['get-filepath'].output.result }}
content: ${{ steps['serialize-patch'].output.serialized }}
- id: read-file
name: Read File
action: roadiehq:utils:fs:parse
input:
path: ${{ steps['get-filepath'].output.result }}
- id: parse-url
name: Parse URL for PR
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
{
"owner": $split($, "/")[3],
"repo": $split($, "/")[4],
"branch": $split($, "/")[6]
}
- id: format-branch-name
name: Format Branch Name
action: roadiehq:utils:jsonata
input:
data: ${{ steps['validate-url'].output.result }}
expression: |
"backstage-sourced-update-" & $join($filter($split($, "/"), function($v, $i) { $i >= 7}), "-")
- id: create-pull-request
name: create-pull-request
action: publish:github:pull-request
input:
repoUrl: ${{ 'github.com?owner=' + steps['parse-url'].output.result.owner + '&repo=' + steps['parse-url'].output.result.repo }}
branchName: ${{ steps['format-branch-name'].output.result }}
title: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
description: Updating Kubernetes YAML for ${{ steps['get-entity'].output.entity.metadata.name }}
targetBranchName: ${{ steps['parse-url'].output.result.branch }}
output:
links:
- title: Pull Request
url: ${{ steps['create-pull-request'].output.remoteUrl }}
- title: Download YAML Manifest
url: data:application/yaml;charset=utf-8,${{ steps['read-file'].output.content }}
Best Practices#
-
Template Design
- Use clear, descriptive titles
- Provide helpful descriptions
- Set appropriate default values
- Include validation rules
-
Repository Structure
- Organize manifests logically
- Use consistent file paths
- Follow GitOps practices
- Maintain clear documentation
-
Pull Requests
- Use descriptive titles
- Provide detailed descriptions
- Apply appropriate labels
- Follow team conventions
For installation instructions, refer to the Installation Guide.