Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: release-service
title: πŸš€ Release Service
title: Release Service

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The rocket emoji has been removed from the template title. While the PR description mentions this is for "consistency", it would be helpful to verify this aligns with the actual convention. The provision-database template still uses an emoji (πŸ—„οΈ) and update-environment uses βš™οΈ. If the goal is to remove emojis for consistency, those templates should be updated as well, or this template should retain its emoji.

Suggested change
title: Release Service
title: πŸš€ Release Service

Copilot uses AI. Check for mistakes.
description: Build and release a service to the preview cluster. Provide a host for web services, or leave empty for a background worker.
tags:
- release
Expand All @@ -14,87 +14,77 @@ metadata:
spec:
owner: group:admin
type: deployment
presentation:
buttonLabels:
createButtonText: 'Release Service'
reviewButtonText: 'Review & Release'

parameters:
- title: Component Info
- title: Service & Source
required:
- teamName
- serviceName
- dockerfileRepo
- gitTag
properties:
teamName:
title: Team Name
title: Team
type: string
description: "Select your team"
ui:field: MyGroupsPicker
serviceName:
title: Component Name
type: string
pattern: "^[a-z0-9][a-z0-9-]{0,62}$"

- title: Source Repository
required:
- dockerfileRepo
- gitTag
properties:
dockerfileRepo:
title: GitHub Repository
type: string
description: >-
owner/repo containing the Dockerfile (e.g. dmitriimashkov/my-app).
For private repos: install the GitHub App at https://github.com/apps/mctl-me/installations/new
or provide a PAT below.
description: "Repository containing the Dockerfile (e.g. dmitriimashkov/my-app). The repo name will be used as the service name."

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The description states "The repo name will be used as the service name" but doesn't warn users about naming constraints. Since Kubernetes resource names must be lowercase alphanumeric with hyphens only (max 63 chars), and GitHub repository names can contain uppercase, dots, and underscores, this could lead to confusing failures if users provide repos with incompatible names (e.g., "owner/My.Service").

Consider adding a warning to the description, such as: "Repository containing the Dockerfile (e.g. dmitriimashkov/my-app). The repo name will be used as the service name and must be lowercase with hyphens only."

Suggested change
description: "Repository containing the Dockerfile (e.g. dmitriimashkov/my-app). The repo name will be used as the service name."
description: "Repository containing the Dockerfile (e.g. dmitriimashkov/my-app). The repo name will be used as the service name and must be lowercase with hyphens only to be a valid Kubernetes service name."

Copilot uses AI. Check for mistakes.

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The repository description previously included a helpful link to install the GitHub App ("install the GitHub App at https://github.com/apps/mctl-me/installations/new"). This link has been removed in favor of a more concise description. Consider retaining the installation link in the repoPat field description or in the dockerfileRepo description, as it helps users understand the alternative to providing a PAT.

Copilot uses AI. Check for mistakes.
pattern: "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$"

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The removal of the serviceName parameter and its validation pattern is a breaking change that eliminates an important safeguard. The previous pattern ^[a-z0-9][a-z0-9-]{0,62}$ ensured the service name would be valid for Kubernetes resource names and DNS labels.

With the automatic derivation from dockerfileRepo, there's no validation to ensure the extracted repo name will be Kubernetes-compatible. Repository names can contain uppercase letters, dots, and underscores (per the pattern on line 38), which are not valid in Kubernetes resource names.

Consider either:

  1. Keeping the serviceName field as an editable field with a default value derived from the repo name, or
  2. Adding validation/transformation logic to ensure the derived name is Kubernetes-compatible
Suggested change
pattern: "^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$"
pattern: "^[a-zA-Z0-9._-]+/[a-z0-9][a-z0-9-]{0,62}$"

Copilot uses AI. Check for mistakes.
repoPat:
title: Repository PAT (optional)
type: string
description: >-
Only needed if the GitHub App is not installed on this repo.
Fine-grained PAT with 'Contents: Read' scope.

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The updated description removes the helpful link to create a PAT (previously included: "Create at: https://github.com/settings/tokens?type=beta"). While the new description is more concise, it would be helpful to retain this link or mention where users can create the PAT, as finding the correct settings page can be non-obvious for users unfamiliar with GitHub's fine-grained tokens.

Suggested change
Fine-grained PAT with 'Contents: Read' scope.
Fine-grained PAT with 'Contents: Read' scope. Create at: https://github.com/settings/tokens?type=beta

Copilot uses AI. Check for mistakes.
ui:field: Secret
Comment on lines +39 to +45

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The repoPat field has been moved within the same section but is now positioned between dockerfileRepo and dockerfilePath, which breaks the logical flow. The PAT is an authentication credential, while dockerfilePath is a path configuration related to dockerfileRepo.

Consider moving repoPat after dockerfilePath to maintain better logical grouping: repository β†’ path β†’ version tag β†’ authentication.

Copilot uses AI. Check for mistakes.
dockerfilePath:
title: Dockerfile Path
type: string
default: Dockerfile
gitTag:
title: Git Tag
title: Version Tag
type: string
description: "Semver tag to checkout and build (e.g., v1.0.0)."
description: "Semver tag to checkout and build (e.g. v1.0.0)"
pattern: "^v?[0-9]+\\.[0-9]+\\.[0-9]+.*$"
repoPat:
title: Repository PAT (private repos only β€” optional if GitHub App is installed)
type: string
description: >-
Only needed if the GitHub App is not installed on this repo.
Fine-grained PAT with 'Contents: Read' scope.
Create at: https://github.com/settings/tokens?type=beta
ui:field: Secret

- title: Network Configuration (optional)
- title: Networking
properties:
port:
title: Port
type: number
default: 8080
description: "HTTP port. Required for web services with ingress."
description: "Container port exposed by the service."
host:
title: Ingress Host
type: string
description: "Ingress hostname (e.g. myapp.preview.mctl.me). Leave empty to deploy as a background worker."
description: "Public hostname (e.g. myapp.preview.mctl.me). Leave empty for a background worker β€” no ingress will be created."

- title: Environment Variables
- title: Environment
properties:
envVars:
title: Environment Variables (non-secret)
title: Environment Variables
type: string
description: "Plaintext KEY=value pairs (one per line). Will be visible in Kubernetes manifests."
description: "KEY=VALUE pairs, one per line. Stored as plaintext in GitOps manifests β€” do not put secrets here."
ui:widget: textarea
ui:options:
rows: 5
ui:placeholder: |
APP_ENV=production
LOG_LEVEL=info
PORT=8080
TIMEOUT_SECONDS=30

- title: Secrets
- title: Secure Variables
properties:
secretEnvVars:
title: Secret Environment Variables
title: Secure Variables
type: string
description: "Plaintext KEY=value pairs (one per line). Will be stored in Vault and injected securely."
description: "KEY=VALUE pairs, one per line. Stored securely in Vault β€” never exposed in Git."
ui:widget: textarea
ui:options:
minRows: 10
Expand All @@ -110,7 +100,7 @@ spec:
action: http:backstage:request
input:
method: POST
path: /proxy/vault/v1/secret/data/teams/${{ parameters.teamName | parseEntityRef | pick('name') }}/${{ parameters.serviceName }}/repo-pat
path: /proxy/vault/v1/secret/data/teams/${{ parameters.teamName | parseEntityRef | pick('name') }}/${{ parameters.dockerfileRepo | repoName }}/repo-pat

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The repoName filter is not a standard Backstage scaffolder filter. This will cause the template to fail at runtime when trying to process this expression.

If this is intended to extract the repository name from "owner/repo" format (e.g., "dmitriimashkov/my-app" β†’ "my-app"), you'll need to either:

  1. Define a custom filter in the Backstage app configuration, or
  2. Use a different approach to extract the repo name

Additionally, even if the filter exists, there's a validation mismatch: the GitHub Actions workflow expects component_name to match the pattern ^[a-z0-9][a-z0-9-]{0,62}$ (lowercase alphanumeric with hyphens), but repository names can contain uppercase letters, dots, and underscores according to the dockerfileRepo pattern. The filter would need to normalize the extracted name to be Kubernetes-compatible.

Copilot uses AI. Check for mistakes.
headers:
Content-Type: application/json
body:
Expand All @@ -127,7 +117,7 @@ spec:
workflowInputs:
action: onboard
team_name: ${{ parameters.teamName | parseEntityRef | pick('name') }}
component_name: ${{ parameters.serviceName }}
component_name: ${{ parameters.dockerfileRepo | repoName }}

Copilot AI Feb 20, 2026

Copy link

Choose a reason for hiding this comment

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

The same repoName filter issue applies here. This filter is not a standard Backstage scaffolder filter and will cause runtime failures. The component_name value passed to the GitHub Actions workflow must match the pattern ^[a-z0-9][a-z0-9-]{0,62}$ as validated in the workflow, but there's no guarantee that extracting the repo name from dockerfileRepo will produce a valid value.

Copilot uses AI. Check for mistakes.
component_type: ${{ 'base-service' if parameters.host else 'worker-service' }}
dockerfile_repo: ${{ parameters.dockerfileRepo }}
dockerfile_path: ${{ parameters.dockerfilePath | default('Dockerfile') }}
Expand All @@ -138,7 +128,17 @@ spec:
secret_env_vars: ${{ parameters.secretEnvVars | default('') }}

output:
text:
- title: Type
content: "${{ 'Web Service' if parameters.host else 'Background Worker' }}"
- title: Version
content: "${{ parameters.gitTag }}"
- title: Preview URL
content: "${{ 'https://' + parameters.host if parameters.host else 'N/A β€” background worker' }}"
links:
- title: View release run
- title: Release Pipeline
icon: github
url: https://github.com/dmitriimashkov/mctl.me/actions/workflows/release-service.yml
- title: ArgoCD Dashboard
icon: dashboard
url: "https://argocd.preview.mctl.me"
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,31 @@ spec:
type: configuration

parameters:
- title: Component
- title: Service
required:
- teamName
- serviceName
properties:
teamName:
title: Team Name
title: Team
type: string
description: "Select your team"
ui:field: MyGroupsPicker
serviceName:
title: Component Name
title: Service Name
type: string
description: "Select the deployed component to update"
description: "Select the deployed service to update"
ui:field: OwnedEntityPicker
ui:options:
allowedKinds:
- Component

- title: Environment Variables (non-secret)
- title: Environment
properties:
envVars:
title: Environment Variables
type: string
description: "Plaintext KEY=value pairs (one per line). Stored in git β€” visible in Kubernetes manifests."
description: "KEY=VALUE pairs, one per line. Stored as plaintext in GitOps manifests β€” do not put secrets here."
ui:widget: textarea
ui:options:
rows: 6
Expand All @@ -48,12 +48,12 @@ spec:
TIMEOUT_SECONDS=30
FEATURE_FLAG=true

- title: Secrets
- title: Secure Variables
properties:
secretEnvVars:
title: Secret Environment Variables
title: Secure Variables
type: string
description: "Plaintext KEY=value pairs (one per line). Will be stored in Vault and injected securely."
description: "KEY=VALUE pairs, one per line. Stored securely in Vault β€” never exposed in Git."
ui:widget: textarea
ui:options:
minRows: 10
Expand Down Expand Up @@ -82,7 +82,7 @@ spec:
text:
- title: Summary
content: |
**Component:** `${{ parameters.teamName | parseEntityRef | pick('name') }}/${{ parameters.serviceName | parseEntityRef | pick('name') }}`
**Service:** `${{ parameters.teamName | parseEntityRef | pick('name') }}/${{ parameters.serviceName | parseEntityRef | pick('name') }}`

${{ parameters.secretEnvVars and 'βœ… **Secrets** update dispatched β€” will be stored in Vault and synced to Kubernetes automatically.' or '' }}

Expand Down