|
| 1 | +# Template Update Pull Requests |
| 2 | + |
| 3 | +This plugin can automatically create pull requests (or merge requests for GitLab) to keep scaffolded repositories in sync with their source templates. When a template version changes, the plugin compares the template files with the scaffolded repository and creates a PR with any necessary updates. |
| 4 | + |
| 5 | +## How It Works |
| 6 | + |
| 7 | +1. **Template Update Detection**: When the plugin detects that a scaffolder template has been updated to a new version, it triggers the PR creation process for all entities scaffolded from that template. |
| 8 | + |
| 9 | +2. **File Comparison**: The plugin fetches files from both the template repository and each scaffolded repository, then compares them to identify: |
| 10 | + |
| 11 | + - Files that need to be **updated** (content differs between template and scaffolded repo) |
| 12 | + - Files that need to be **created** (exist in template but not in scaffolded repo) |
| 13 | + - Files that need to be **deleted** (exist in scaffolded repo but no longer in template) |
| 14 | + |
| 15 | +3. **PR Creation**: For each scaffolded entity with differences, a pull request is created containing all the necessary file changes. |
| 16 | + |
| 17 | +4. **Reviewer Assignment**: If the scaffolded entity's owner is a **User** (not a Group), they are automatically assigned as a reviewer on the PR. |
| 18 | + |
| 19 | +5. **Notification**: If notifications are enabled, entity owners receive a notification with a link to the created PR. |
| 20 | + |
| 21 | +> ⚠️ **Important**: Always manually review the generated pull requests before merging. The automatic comparison may include changes that are intentionally different in your scaffolded repository, or may not account for project-specific customizations. |
| 22 | +
|
| 23 | +## Prerequisites |
| 24 | + |
| 25 | +### VCS Integration Configuration |
| 26 | + |
| 27 | +The plugin requires appropriate VCS (Version Control System) integrations to be configured in your `app-config.yaml`. The plugin currently supports **GitHub** and **GitLab**. |
| 28 | + |
| 29 | +For detailed configuration of these integrations, see the [Backstage Integrations documentation](https://backstage.io/docs/integrations/). |
| 30 | + |
| 31 | +### Entity Requirements |
| 32 | + |
| 33 | +For the PR feature to work, scaffolded entities must have: |
| 34 | + |
| 35 | +1. **`spec.scaffoldedFrom`**: Reference to the template entity (e.g., `template:default/my-template`) |
| 36 | + |
| 37 | +2. **`backstage.io/managed-by-location`**: This annotation is automatically added by the catalog during entity fetching and points to the source location from which the entity was fetched. The plugin uses this annotation to determine the repository URL for the scaffolded entity. |
| 38 | + |
| 39 | + > **Note**: The PR feature only works when this annotation is of type `url` and points to a GitHub or GitLab repository. Entities registered from other location types (e.g., `file`) are not supported for automatic PR creation. |
| 40 | +
|
| 41 | +## Configuration |
| 42 | + |
| 43 | +Enable the PR feature in your `app-config.yaml`: |
| 44 | + |
| 45 | +```yaml |
| 46 | +scaffolder: |
| 47 | + pullRequests: |
| 48 | + templateUpdate: |
| 49 | + enabled: true |
| 50 | +``` |
| 51 | +
|
| 52 | +### Combined with Notifications |
| 53 | +
|
| 54 | +You can enable both PR creation and notifications together. Here's the behavior for each combination: |
| 55 | +
|
| 56 | +- **Both disabled**: No action taken on template updates |
| 57 | +- **Only notifications enabled**: Notification sent to entity owners with link to catalog |
| 58 | +- **Only PRs enabled**: PR created, no notification sent |
| 59 | +- **Both enabled**: PR created, notification sent with link to PR |
| 60 | +
|
| 61 | +Example configuration with both features enabled: |
| 62 | +
|
| 63 | +```yaml |
| 64 | +scaffolder: |
| 65 | + notifications: |
| 66 | + templateUpdate: |
| 67 | + enabled: true |
| 68 | + message: |
| 69 | + title: '$ENTITY_DISPLAY_NAME has a template update PR ready' |
| 70 | + description: 'A pull request has been created to sync template changes: $PR_LINK' |
| 71 | + pullRequests: |
| 72 | + templateUpdate: |
| 73 | + enabled: true |
| 74 | +``` |
| 75 | +
|
| 76 | +When PRs are enabled, you can use the `$PR_LINK` template variable in your notification message to include a link to the created PR. If the PR creation fails, a notification with default (not custom) text is still sent along with error details. |
| 77 | + |
| 78 | +## PR Details |
| 79 | + |
| 80 | +### Branch Naming |
| 81 | + |
| 82 | +PRs are created on a branch named: |
| 83 | + |
| 84 | +``` |
| 85 | +[component-name]/template-upgrade-v[new-version] |
| 86 | +``` |
| 87 | + |
| 88 | +For example: `my-service/template-upgrade-v1.2.0` |
| 89 | + |
| 90 | +### PR Title |
| 91 | + |
| 92 | +``` |
| 93 | +Template Upgrade: Update [Template Name] from [old-version] to [new-version] |
| 94 | +``` |
| 95 | +
|
| 96 | +## Reviewer Assignment |
| 97 | +
|
| 98 | +The plugin automatically assigns a reviewer to the PR if the scaffolded entity's owner is a **User** entity (not a Group). The reviewer assignment works as follows: |
| 99 | +
|
| 100 | +### For GitHub |
| 101 | +
|
| 102 | +The plugin looks for the `github.com/user-login` annotation on the owner User entity: |
| 103 | +
|
| 104 | +```yaml |
| 105 | +# User entity example |
| 106 | +apiVersion: backstage.io/v1alpha1 |
| 107 | +kind: User |
| 108 | +metadata: |
| 109 | + name: john.doe |
| 110 | + annotations: |
| 111 | + github.com/user-login: johndoe # GitHub username |
| 112 | +spec: |
| 113 | + profile: |
| 114 | + displayName: John Doe |
| 115 | +``` |
| 116 | + |
| 117 | +### For GitLab |
| 118 | + |
| 119 | +The plugin looks for the `gitlab.com/user-login` annotation on the owner User entity: |
| 120 | + |
| 121 | +```yaml |
| 122 | +# User entity example |
| 123 | +apiVersion: backstage.io/v1alpha1 |
| 124 | +kind: User |
| 125 | +metadata: |
| 126 | + name: john.doe |
| 127 | + annotations: |
| 128 | + gitlab.com/user-login: johndoe # GitLab username |
| 129 | +spec: |
| 130 | + profile: |
| 131 | + displayName: John Doe |
| 132 | +``` |
| 133 | +
|
| 134 | +If the owner is a **Group** or the user annotation is not present, the PR is created without a reviewer assignment. |
| 135 | +
|
| 136 | +## Error Handling |
| 137 | +
|
| 138 | +### No Changes Detected |
| 139 | +
|
| 140 | +If there are no differences between the template and the scaffolded repository, no PR is created and no notification is sent for that entity. |
| 141 | +
|
| 142 | +### PR Creation Failures |
| 143 | +
|
| 144 | +If PR creation fails (e.g., authentication issues, API errors), the plugin: |
| 145 | +
|
| 146 | +- Logs the error |
| 147 | +- Sends a notification to the entity owner (if notifications are enabled) with error details |
| 148 | +- The notification uses a default message indicating the failure, regardless of any custom message configuration |
| 149 | +
|
| 150 | +Common failure reasons: |
| 151 | +
|
| 152 | +- Missing or invalid VCS integration credentials |
| 153 | +- Insufficient permissions to create branches or PRs |
| 154 | +- Network connectivity issues |
| 155 | +- Rate limiting by the VCS provider |
| 156 | +
|
| 157 | +## Limitations |
| 158 | +
|
| 159 | +- **Template variable resolution**: During file comparison, the plugin attempts to replace template variables (e.g., `${{ values.name }}`) with the actual values from the scaffolded repository by matching YAML keys. However, this has limitations: |
| 160 | + |
| 161 | + - If a key cannot be matched between the template and scaffolded file, the raw template syntax will appear in the PR and must be resolved manually |
| 162 | + - Variables that were left empty during scaffolding may appear as differences |
| 163 | + - Only simple key-value patterns are matched; inline variables or complex nested structures may not be resolved correctly |
| 164 | + - Jinja2 conditionals (`{% if %}`, `{% endif %}`, etc.) are automatically stripped, but conditional content may still cause unexpected differences |
| 165 | + |
| 166 | +- **File-based comparison only**: The plugin compares files at the repository root level based on the entity's managed-by-location annotation. It does not handle complex template structures with multiple directories. |
| 167 | + |
| 168 | +- **No conflict resolution**: If the scaffolded repository has diverged significantly from the template, the PR may contain merge conflicts that need manual resolution. |
| 169 | + |
| 170 | +- **Single PR per template update**: Each template version change creates new PRs for all scaffolded entities. If a previous PR is still open, the creation may fail if a branch with the same name already exists. |
| 171 | + |
| 172 | +## Troubleshooting |
| 173 | + |
| 174 | +### PRs Not Being Created |
| 175 | + |
| 176 | +1. **Check VCS integration**: Ensure your `app-config.yaml` has the correct integration configured for your VCS provider. |
| 177 | + |
| 178 | +2. **Check entity annotations**: Verify that scaffolded entities have the `backstage.io/managed-by-location` annotation pointing to a valid repository URL. |
| 179 | + |
| 180 | +3. **Check logs**: Look for error messages in the Backstage backend logs related to `scaffolder-relation-processor`. |
| 181 | + |
| 182 | +4. **Verify permissions**: Ensure the token or GitHub App has permissions to: |
| 183 | + - Read repository contents |
| 184 | + - Create branches |
| 185 | + - Create pull requests |
| 186 | + - Request reviewers (for reviewer assignment) |
| 187 | + |
| 188 | +### Reviewer Not Being Assigned |
| 189 | + |
| 190 | +1. **Check owner type**: Reviewer assignment only works for User entities, not Groups. |
| 191 | + |
| 192 | +2. **Check user annotations**: Ensure the owner User entity has the appropriate VCS login annotation (`github.com/user-login` or `gitlab.com/user-login`). |
0 commit comments