From f391b59ddb0d83fc9d4ed921fea7d5481c1cc417 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:41:30 +0000 Subject: [PATCH 1/4] Initial plan From 1372ccfc0fa92087c725ec78b6bee73ccfc18ef5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 16 Jul 2025 15:57:09 +0000 Subject: [PATCH 2/4] Add prominent warnings about kebab-case action IDs causing NaN in scaffolder templates --- docs/features/software-templates/index.md | 12 ++++++ .../migrating-from-v1beta2-to-v1beta3.md | 39 +++++++++++++++++++ .../writing-custom-actions.md | 10 +++++ .../software-templates/writing-templates.md | 8 ++++ 4 files changed, 69 insertions(+) diff --git a/docs/features/software-templates/index.md b/docs/features/software-templates/index.md index 16f7c3cbbd..7a019838da 100644 --- a/docs/features/software-templates/index.md +++ b/docs/features/software-templates/index.md @@ -10,6 +10,18 @@ Components inside Backstage. By default, it has the ability to load skeletons of code, template in some variables, and then publish the template to some locations like GitHub or GitLab. +:::warning Important + +When creating custom scaffolder actions, **use camelCase for action IDs** instead of kebab-case. Action IDs with dashes (like `fetch:component-id`) will cause template expressions like `${{ steps.fetch-component-id.output.componentId }}` to return `NaN` because the dashes are evaluated as subtraction operators in JavaScript expressions. + +Use `fetchComponentId` instead of `fetch:component-id` for action IDs, or access outputs using bracket notation: `${{ steps['fetch:component-id'].output.componentId }}`. + +:::note + +See the [Writing Custom Actions guide](./writing-custom-actions.md#naming-conventions) and [Template Migration guide](./migrating-from-v1beta2-to-v1beta3.md#watch-out-for-dash-case) for more details. + +::: + ## Prerequisites :::note Note diff --git a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md index 91fc34f978..19d8e3c03d 100644 --- a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md +++ b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md @@ -202,6 +202,45 @@ output: ## Watch out for `dash-case` +:::warning Critical Issue: kebab-case Action IDs Cause NaN + +The nunjucks compiler can run into issues if the `id` fields in your template steps use dash characters, since these IDs translate directly to JavaScript object properties when accessed as output. **This is a common source of bugs where template expressions return `NaN` instead of expected values.** + +**The Problem:** +When you use kebab-case action IDs like `fetch:component-id`, template expressions like: +```yaml +${{ steps.fetch-component-id.output.componentId }} +``` +Are evaluated as JavaScript: `steps.fetch - component - id.output.componentId`, which performs subtraction operations and results in `NaN`. + +**Solutions:** + +1. **Recommended:** Use `camelCase` for your action IDs: + +```yaml +steps: + - id: fetchComponentId # ✅ Use camelCase + ... + + - id: publishPullRequest # ✅ Use camelCase + input: + repoUrl: ${{ steps.fetchComponentId.output.repoUrl }} # ✅ Works correctly +``` + +2. **Alternative:** Keep dash-case and use bracket notation for property access: + +```yaml +steps: + - id: fetch-component-id # ⚠️ Dash-case requires bracket notation + ... + + - id: publish-pull-request + input: + repoUrl: ${{ steps['fetch-component-id'].output.repoUrl }} # ✅ Works with brackets +``` + +::: + The nunjucks compiler can run into issues if the `id` fields in your template steps use dash characters, since these IDs translate directly to JavaScript object properties when accessed as output. One possible migration path is to use `camelCase` for your action IDs. ```yaml diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 1a64406b04..e7202a4a6e 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -105,6 +105,16 @@ We follow `provider:entity:verb` or as close to this as possible for our built-i Also feel free to use your company name to namespace them if you prefer too, for example `acme:file:create` like above. +:::warning Critical: Use camelCase for Action IDs + +**Always use `camelCase` for action IDs** instead of `kebab-case` or `snake_case`. Action IDs with dashes (like `fetch:component-id`) will cause your template expressions to return `NaN` instead of expected values. + +**Problem:** If you use kebab-case like `fetch:component-id`, expressions like `${{ steps.fetch-component-id.output.componentId }}` will be evaluated as `steps.fetch - component - id.output.componentId` (subtraction operations), resulting in `NaN`. + +**Solution:** Use `fetchComponentId` instead of `fetch:component-id`, or access outputs with bracket notation: `${{ steps['fetch:component-id'].output.componentId }}`. + +::: + Prefer to use `camelCase` over `snake_case` or `kebab-case` for these actions if possible, which leads to better reading and writing of template entity definitions. diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 7433f664ce..0c1ae23aa8 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -633,6 +633,14 @@ template. These follow the same standard format: name: ${{ parameters.name }} ``` +:::warning Action ID Naming + +When using custom actions, **use camelCase for action IDs** to avoid issues with template expressions. Action IDs with dashes will cause expressions like `${{ steps.my-action.output.value }}` to return `NaN` instead of the expected value. + +Use `myAction` instead of `my-action`, or access outputs with bracket notation: `${{ steps['my-action'].output.value }}`. + +::: + By default we ship some [built in actions](./builtin-actions.md) that you can take a look at, or you can [create your own custom actions](./writing-custom-actions.md). From ad56ea941793064abecd8cce57614a48d8315334 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 16 Jul 2025 16:52:15 +0000 Subject: [PATCH 3/4] Replace non-camelCase task IDs with camelCase equivalents Co-authored-by: Rugvip <4984472+Rugvip@users.noreply.github.com> --- docs/features/software-templates/adding-templates.md | 4 ++-- docs/features/software-templates/builtin-actions.md | 2 +- docs/features/software-templates/experimental.md | 4 ++-- docs/features/software-templates/writing-templates.md | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/features/software-templates/adding-templates.md b/docs/features/software-templates/adding-templates.md index ffaa9a3e66..55c99aa694 100644 --- a/docs/features/software-templates/adding-templates.md +++ b/docs/features/software-templates/adding-templates.md @@ -49,7 +49,7 @@ spec: # here's the steps that are executed in series in the scaffolder backend steps: - - id: fetch-base + - id: fetchBase name: Fetch Base action: fetch:template input: @@ -57,7 +57,7 @@ spec: values: name: ${{ parameters.name }} - - id: fetch-docs + - id: fetchDocs name: Fetch Docs action: fetch:plain input: diff --git a/docs/features/software-templates/builtin-actions.md b/docs/features/software-templates/builtin-actions.md index d732bd8a27..22d8ef6454 100644 --- a/docs/features/software-templates/builtin-actions.md +++ b/docs/features/software-templates/builtin-actions.md @@ -78,7 +78,7 @@ allow most templates built for `fetch:cookiecutter` to work without any changes. ```yaml title="template.yaml" steps: - - id: fetch-base + - id: fetchBase name: Fetch Base # highlight-remove-next-line action: fetch:cookiecutter diff --git a/docs/features/software-templates/experimental.md b/docs/features/software-templates/experimental.md index 1df041d7a2..ff40120d8c 100644 --- a/docs/features/software-templates/experimental.md +++ b/docs/features/software-templates/experimental.md @@ -100,7 +100,7 @@ metadata: name: my-template spec: EXPERIMENTAL_formDecorators: - - id: my-decorator + - id: myDecorator input: test: something funky @@ -115,7 +115,7 @@ You can create a decorator using the simple helper method `createScaffolderFormD ```ts export const mockDecorator = createScaffolderFormDecorator({ // give the decorator a name - id: 'mock-decorator', + id: 'mockDecorator', // define the schema for the input that can be provided in `template.yaml` schema: { diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index 0c1ae23aa8..c39e4e80bb 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -59,7 +59,7 @@ spec: # here's the steps that are executed in series in the scaffolder backend steps: - - id: fetch-base + - id: fetchBase name: Fetch Base action: fetch:template input: @@ -68,7 +68,7 @@ spec: name: ${{ parameters.name }} owner: ${{ parameters.owner }} - - id: fetch-docs + - id: fetchDocs name: Fetch Docs action: fetch:plain input: @@ -87,7 +87,7 @@ spec: name: Register action: catalog:register input: - repoContentsUrl: ${{ steps['publish'].output.repoContentsUrl }} + repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }} catalogInfoPath: '/catalog-info.yaml' # some outputs which are saved along with the job for use in the frontend @@ -622,7 +622,7 @@ The `steps` is an array of the things that you want to happen part of this template. These follow the same standard format: ```yaml -- id: fetch-base # A unique id for the step +- id: fetchBase # A unique id for the step name: Fetch Base # A title displayed in the frontend if: ${{ parameters.name }} # Optional condition, skip the step if not truthy each: ${{ parameters.iterable }} # Optional iterable, run the same step multiple times @@ -732,7 +732,7 @@ spec: default: false ... steps: - - id: fetch-base + - id: fetchBase name: Fetch Base action: fetch:template input: From 2f940b0aec38c2d5370cef83895b8a4870e9990c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 16 Jul 2025 17:46:02 +0000 Subject: [PATCH 4/4] Address review feedback: simplify warning text and revert migration/custom action docs Co-authored-by: Rugvip <4984472+Rugvip@users.noreply.github.com> --- docs/features/software-templates/index.md | 4 +- .../migrating-from-v1beta2-to-v1beta3.md | 39 ------------------- .../writing-custom-actions.md | 10 ----- 3 files changed, 1 insertion(+), 52 deletions(-) diff --git a/docs/features/software-templates/index.md b/docs/features/software-templates/index.md index 7a019838da..58da85c6eb 100644 --- a/docs/features/software-templates/index.md +++ b/docs/features/software-templates/index.md @@ -12,9 +12,7 @@ locations like GitHub or GitLab. :::warning Important -When creating custom scaffolder actions, **use camelCase for action IDs** instead of kebab-case. Action IDs with dashes (like `fetch:component-id`) will cause template expressions like `${{ steps.fetch-component-id.output.componentId }}` to return `NaN` because the dashes are evaluated as subtraction operators in JavaScript expressions. - -Use `fetchComponentId` instead of `fetch:component-id` for action IDs, or access outputs using bracket notation: `${{ steps['fetch:component-id'].output.componentId }}`. +When creating custom scaffolder actions, **use camelCase for action IDs** instead of kebab-case. Action IDs with dashes (like `fetch-component-id`) will cause template expressions like `${{ steps.fetch-component-id.output.componentId }}` to return `NaN` because the dashes are evaluated as subtraction operators in JavaScript expressions. :::note diff --git a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md index 19d8e3c03d..91fc34f978 100644 --- a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md +++ b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md @@ -202,45 +202,6 @@ output: ## Watch out for `dash-case` -:::warning Critical Issue: kebab-case Action IDs Cause NaN - -The nunjucks compiler can run into issues if the `id` fields in your template steps use dash characters, since these IDs translate directly to JavaScript object properties when accessed as output. **This is a common source of bugs where template expressions return `NaN` instead of expected values.** - -**The Problem:** -When you use kebab-case action IDs like `fetch:component-id`, template expressions like: -```yaml -${{ steps.fetch-component-id.output.componentId }} -``` -Are evaluated as JavaScript: `steps.fetch - component - id.output.componentId`, which performs subtraction operations and results in `NaN`. - -**Solutions:** - -1. **Recommended:** Use `camelCase` for your action IDs: - -```yaml -steps: - - id: fetchComponentId # ✅ Use camelCase - ... - - - id: publishPullRequest # ✅ Use camelCase - input: - repoUrl: ${{ steps.fetchComponentId.output.repoUrl }} # ✅ Works correctly -``` - -2. **Alternative:** Keep dash-case and use bracket notation for property access: - -```yaml -steps: - - id: fetch-component-id # ⚠️ Dash-case requires bracket notation - ... - - - id: publish-pull-request - input: - repoUrl: ${{ steps['fetch-component-id'].output.repoUrl }} # ✅ Works with brackets -``` - -::: - The nunjucks compiler can run into issues if the `id` fields in your template steps use dash characters, since these IDs translate directly to JavaScript object properties when accessed as output. One possible migration path is to use `camelCase` for your action IDs. ```yaml diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index e7202a4a6e..1a64406b04 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -105,16 +105,6 @@ We follow `provider:entity:verb` or as close to this as possible for our built-i Also feel free to use your company name to namespace them if you prefer too, for example `acme:file:create` like above. -:::warning Critical: Use camelCase for Action IDs - -**Always use `camelCase` for action IDs** instead of `kebab-case` or `snake_case`. Action IDs with dashes (like `fetch:component-id`) will cause your template expressions to return `NaN` instead of expected values. - -**Problem:** If you use kebab-case like `fetch:component-id`, expressions like `${{ steps.fetch-component-id.output.componentId }}` will be evaluated as `steps.fetch - component - id.output.componentId` (subtraction operations), resulting in `NaN`. - -**Solution:** Use `fetchComponentId` instead of `fetch:component-id`, or access outputs with bracket notation: `${{ steps['fetch:component-id'].output.componentId }}`. - -::: - Prefer to use `camelCase` over `snake_case` or `kebab-case` for these actions if possible, which leads to better reading and writing of template entity definitions.