|
| 1 | +| Authors | Creation Date | Status | Extra | |
| 2 | +|-----------------|---------------|-------------|-------| |
| 3 | +| @camilamacedo86 | 2024-11-07 | Implementable | - | |
| 4 | + |
| 5 | +# Proposal: Automating maintenance via tooling and actions |
| 6 | + |
| 7 | +Kubebuilder is widely used for developing Kubernetes operators, offering a standardized scaffold for projects. |
| 8 | +However, as the ecosystem evolves, keeping projects up-to-date becomes challenging due to: |
| 9 | + |
| 10 | +- **Manual re-scaffolding processes**: These are time-intensive and error-prone. |
| 11 | +- **Increased risk of outdated configurations**: This leads to security vulnerabilities or incompatibility with modern practices. |
| 12 | + |
| 13 | +This proposal introduces a tool that can be called via workflows like GitHub Action to handle updates |
| 14 | +for projects created with Kubebuilder. When a new version of Kubebuilder is released, it would be easier |
| 15 | +to upgrade projects, as users would receive a pull request with necessary changes while preserving customizations. |
| 16 | + |
| 17 | +## Example |
| 18 | + |
| 19 | +### Using GitHub Actions: |
| 20 | + |
| 21 | +1. A user creates a project with Kubebuilder `v4.4`. |
| 22 | +2. When Kubebuilder `v4.5` is released, a pull request is automatically created. |
| 23 | +3. The pull request includes updates to the scaffold while preserving the user’s customizations, ready for review and merging. |
| 24 | + |
| 25 | +### Using the Tool Locally: |
| 26 | + |
| 27 | +1. A user creates a project with Kubebuilder `v4.4`. |
| 28 | +2. When Kubebuilder `v4.5` is released, the user runs the tool locally. |
| 29 | +3. The tool updates the scaffold and preserves customizations, allowing the user to review and apply the changes. |
| 30 | + |
| 31 | +In both cases, if conflicts cannot be resolved automatically, developers can manually address |
| 32 | +them before completing the update. |
| 33 | + |
| 34 | +## Open Questions |
| 35 | + |
| 36 | +1. Do we need to create branches to perform the three-way merge, or can we use local temporary directories? |
| 37 | + |
| 38 | +> While temporary directories are sufficient for simple three-way merges, branches are better suited for |
| 39 | +> complex scenarios. They provide history tracking, support collaboration, integrate with CI/CD workflows, |
| 40 | +> and offer more advanced conflict resolution through Git’s merge command. For these reasons, it seems more |
| 41 | +> appropriate the usage of branches to ensure flexibility and maintainability in the merging process. |
| 42 | +
|
| 43 | +2. What Git configuration options can facilitate the three-way merge? |
| 44 | + |
| 45 | +Several Git configuration options can improve the three-way merge process: |
| 46 | + |
| 47 | +```bash |
| 48 | +# Show all three versions (base, current, and updated) during conflicts |
| 49 | +git config --global merge.conflictStyle diff3 |
| 50 | + |
| 51 | +# Enable "reuse recorded resolution" to remember and reuse previous conflict resolutions |
| 52 | +git config --global rerere.enabled true |
| 53 | + |
| 54 | +# Increase the rename detection limit to better handle renamed or moved files |
| 55 | +git config --global merge.renameLimit 999999 |
| 56 | + |
| 57 | +# Set up custom merge drivers for specific file types (e.g., YAML or JSON) |
| 58 | +git config --global merge.<driver>.name "Custom Merge Driver" |
| 59 | +``` |
| 60 | + |
| 61 | +These configurations enhance the merging process by improving conflict visibility, |
| 62 | +reusing resolutions, and providing better file handling, making three-way merges |
| 63 | +more efficient and developer-friendly. |
| 64 | + |
| 65 | +3. If we change Git configurations, can we isolate these changes to avoid affecting the local developer environment when |
| 66 | +the tool runs locally? |
| 67 | + |
| 68 | +It seems that changes can be made using the `-c` flag, which applies the configuration only |
| 69 | +for the duration of a specific Git command. This ensures that the local developer |
| 70 | +environment remains unaffected. |
| 71 | + |
| 72 | +For example: |
| 73 | + |
| 74 | +```bash |
| 75 | +git -c merge.conflictStyle=diff3 -c rerere.enabled=true merge |
| 76 | +``` |
| 77 | + |
| 78 | +4. How can we minimize and resolve conflicts effectively during merges? |
| 79 | + |
| 80 | +- **Enable Git Features:** |
| 81 | + - Use `git config --global rerere.enabled true` to reuse previous conflict resolutions. |
| 82 | + - Configure custom merge drivers for specific file types (e.g., `git config --global merge.<driver>.name "Custom Merge Driver"`). |
| 83 | + |
| 84 | +- **Encourage Standardization:** |
| 85 | + - Adopt a standardized scaffold layout to minimize divergence and reduce conflicts. |
| 86 | + |
| 87 | +- **Apply Frequent Updates:** |
| 88 | + - Regularly update projects to avoid significant drift between the scaffold and customizations. |
| 89 | + |
| 90 | +These strategies help minimize conflicts and simplify their resolution during merges. |
| 91 | + |
| 92 | +## Summary |
| 93 | + |
| 94 | +### Workflow Example: |
| 95 | + |
| 96 | +1. A developer creates a project with Kubebuilder `v4.4`. |
| 97 | +2. The tooling uses the release of Kubebuilder `v4.5`. |
| 98 | +3. The tool: |
| 99 | + - Regenerates the original base source code for `v4.4` using the `clientVersion` in the `PROJECT` file. |
| 100 | + - Generates the base source code for `v4.5` |
| 101 | +4. A three-way merge integrates the changes into the developer’s project while retaining custom code. |
| 102 | +5. The changes now can be packaged into a pull request, summarizing updates and conflicts for the developer’s review. |
| 103 | + |
| 104 | +### Steps: |
| 105 | + |
| 106 | +The proposed implementation involves the following steps: |
| 107 | + |
| 108 | +1. **Version Tracking**: |
| 109 | + - Record the `clientVersion` (initial Kubebuilder version) in the `PROJECT` file. |
| 110 | + - Use this version as a baseline for updates. |
| 111 | + |
| 112 | +2. **Scaffold Generation**: |
| 113 | + - Generate the original scaffold using the stored version. |
| 114 | + - Regenerate the scaffold with the latest Kubebuilder release. |
| 115 | + |
| 116 | +3. **Three-Way Merge**: |
| 117 | + - Ensure git is configured to handle three-way merges. |
| 118 | + - Merge the original scaffold, updated scaffold, and the user’s customized project. |
| 119 | + - Preserve custom code during the merge. |
| 120 | + |
| 121 | +4. **(For Actions) - Pull Request Creation**: |
| 122 | + - Open a pull request summarizing changes, including details on conflict resolution. |
| 123 | + - Schedule updates weekly or provide an on-demand option. |
| 124 | + |
| 125 | +#### Example Workflow |
| 126 | + |
| 127 | +The following example code illustrates the proposed idea but has not been evaluated. |
| 128 | +This is an early, incomplete draft intended to demonstrate the approach and basic concept. |
| 129 | + |
| 130 | +We may want to develop a dedicated command-line tool, such as `kubebuilder alpha update`, |
| 131 | +to handle tasks like downloading binaries, merging, and updating the scaffold. In this approach, |
| 132 | +the GitHub Action would simply invoke this tool to manage the update process and open the |
| 133 | +Pull Request, rather than performing each step directly within the Action itself. |
| 134 | + |
| 135 | +```yaml |
| 136 | + |
| 137 | +name: Update Kubebuilder Scaffold |
| 138 | + |
| 139 | +on: |
| 140 | + workflow_dispatch: |
| 141 | + schedule: |
| 142 | + - cron: '0 0 * * 0' # Run weekly to check for new Kubebuilder versions |
| 143 | + |
| 144 | +jobs: |
| 145 | + update-scaffold: |
| 146 | + runs-on: ubuntu-latest |
| 147 | + |
| 148 | + steps: |
| 149 | + - name: Check out the repository |
| 150 | + uses: actions/checkout@v2 |
| 151 | + with: |
| 152 | + fetch-depth: 0 # Ensures the full history is checked out |
| 153 | + |
| 154 | + - name: Set up environment and dependencies |
| 155 | + run: | |
| 156 | + sudo apt-get update |
| 157 | + sudo apt-get install -y jq curl |
| 158 | +
|
| 159 | + - name: Read Kubebuilder version from PROJECT file |
| 160 | + id: read_version |
| 161 | + run: | |
| 162 | + export INITIAL_VERSION=$(grep "clientVersion" PROJECT | awk '{print $2}') |
| 163 | + echo "::set-output name=initial_version::$INITIAL_VERSION" |
| 164 | +
|
| 165 | + - name: Download and install the initial Kubebuilder version |
| 166 | + run: | |
| 167 | + curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/${{ steps.read_version.outputs.initial_version }}/kubebuilder_${{ steps.read_version.outputs.initial_version }}_linux_amd64.tar.gz -o kubebuilder_initial.tar.gz |
| 168 | + tar -zxvf kubebuilder_initial.tar.gz |
| 169 | + sudo mv kubebuilder /usr/local/kubebuilder_initial |
| 170 | +
|
| 171 | + - name: Generate initial scaffold in `scaffold_initial` directory |
| 172 | + run: | |
| 173 | + mkdir scaffold_initial |
| 174 | + cp -r . scaffold_initial/ |
| 175 | + cd scaffold_initial |
| 176 | + /usr/local/kubebuilder_initial/bin/kubebuilder init |
| 177 | + cd .. |
| 178 | +
|
| 179 | + - name: Check for the latest Kubebuilder release |
| 180 | + id: get_latest_version |
| 181 | + run: | |
| 182 | + export LATEST_VERSION=$(curl -s https://api.github.com/repos/kubernetes-sigs/kubebuilder/releases/latest | jq -r .tag_name) |
| 183 | + echo "::set-output name=latest_version::$LATEST_VERSION" |
| 184 | +
|
| 185 | + - name: Download and install the latest Kubebuilder version |
| 186 | + run: | |
| 187 | + curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/${{ steps.get_latest_version.outputs.latest_version }}/kubebuilder_${{ steps.get_latest_version.outputs.latest_version }}_linux_amd64.tar.gz -o kubebuilder_latest.tar.gz |
| 188 | + tar -zxvf kubebuilder_latest.tar.gz |
| 189 | + sudo mv kubebuilder /usr/local/kubebuilder_latest |
| 190 | +
|
| 191 | + - name: Generate updated scaffold in `scaffold_updated` directory |
| 192 | + run: | |
| 193 | + mkdir scaffold_updated |
| 194 | + cp -r . scaffold_updated/ |
| 195 | + cd scaffold_updated |
| 196 | + /usr/local/kubebuilder_latest/bin/kubebuilder init |
| 197 | + cd .. |
| 198 | +
|
| 199 | + - name: Copy current project into `scaffold_current` directory |
| 200 | + run: | |
| 201 | + mkdir scaffold_current |
| 202 | + cp -r . scaffold_current/ |
| 203 | +
|
| 204 | + - name: Perform three-way merge with scaffolds |
| 205 | + run: | |
| 206 | + # Create a temporary directory to hold the final merged version |
| 207 | + mkdir merged_scaffold |
| 208 | + # Run three-way merge using scaffold_initial, scaffold_current, and scaffold_updated |
| 209 | + # Adjusting merge strategy and paths to use directories |
| 210 | + diff3 -m scaffold_current scaffold_initial scaffold_updated > merged_scaffold/merged_files |
| 211 | +
|
| 212 | + - name: Copy merged files back to main directory |
| 213 | + run: | |
| 214 | + cp -r merged_scaffold/* . |
| 215 | + git add . |
| 216 | + git commit -m "Three-way merge with Kubebuilder updates and custom code" |
| 217 | +
|
| 218 | + - name: Create Pull Request |
| 219 | + uses: peter-evans/create-pull-request@v3 |
| 220 | + with: |
| 221 | + commit-message: "Update scaffold to Kubebuilder ${{ steps.get_latest_version.outputs.latest_version }}" |
| 222 | + title: "Update scaffold to Kubebuilder ${{ steps.get_latest_version.outputs.latest_version }}" |
| 223 | + body: | |
| 224 | + This pull request updates the scaffold with the latest Kubebuilder version ${{ steps.get_latest_version.outputs.latest_version }}. |
| 225 | + branch: kubebuilder-update-${{ steps.get_latest_version.outputs.latest_version }} |
| 226 | +``` |
| 227 | +
|
| 228 | +## Motivation |
| 229 | +
|
| 230 | +A significant challenge faced by Kubebuilder users is keeping their projects up-to-date with the latest |
| 231 | +scaffolds while preserving customizations. The manual processes required for updates are time-consuming, |
| 232 | +error-prone, and often discourage users from adopting new versions, leading to outdated and insecure projects. |
| 233 | +
|
| 234 | +The primary motivation for this proposal is to simplify and automate the process of maintaining Kubebuilder |
| 235 | +projects. By providing a streamlined workflow for updates, this solution ensures that users can keep |
| 236 | +their projects aligned with modern standards while retaining their customizations. |
| 237 | +
|
| 238 | +### Goals |
| 239 | +
|
| 240 | +- **Automate Updates:** Detect and apply scaffold updates while preserving customizations. |
| 241 | +- **Simplify Updates:** Generate pull requests for easy review and merging. |
| 242 | +- **Provide Local Tooling:** Allow updates locally with preserved customizations. |
| 243 | +- **Keep Projects Current:** Ensure alignment with the latest scaffold improvements. |
| 244 | +- **Minimize Disruptions:** Enable scheduled or on-demand updates. |
| 245 | +
|
| 246 | +### Non-Goals |
| 247 | +
|
| 248 | +- Resolving complex conflicts in customizations. |
| 249 | +- Automatically merging updates without review. |
| 250 | +
|
| 251 | +## Proposal |
| 252 | +
|
| 253 | +### User Stories |
| 254 | +
|
| 255 | +- **As a Kubebuilder maintainer**, I want to help users keep their projects updated with minimal effort, ensuring they adhere to best practices and maintain alignment with project standards. |
| 256 | +- **As a user of Kubebuilder**, I want my project to stay up-to-date with the latest scaffold best practices while preserving customizations. |
| 257 | +- **As a user of Kubebuilder**, I want an easy way to apply updates across multiple repositories, saving time on manual updates. |
| 258 | +- **As a user of Kubebuilder**, I want to ensure my codebases remain secure and maintainable without excessive manual effort. |
| 259 | +
|
| 260 | +### Implementation Details/Notes/Constraints |
| 261 | +
|
| 262 | +N/A |
| 263 | +
|
| 264 | +### Risks and Mitigations |
| 265 | +
|
| 266 | +- **Risk**: Potential conflicts with heavily customized code. |
| 267 | + - *Mitigation*: GitHub as other tools provide a preview mode where users can inspect conflicts before the merge is attempted. |
| 268 | +
|
| 269 | +### Proof of Concept |
| 270 | +
|
| 271 | +The feasibility of re-scaffolding projects has been demonstrated by the `kubebuilder alpha generate` command. |
| 272 | + |
| 273 | +**Command Example:** |
| 274 | + |
| 275 | +```bash |
| 276 | +kubebuilder alpha generate |
| 277 | +``` |
| 278 | + |
| 279 | +For more details, refer to the [Alpha Generate Documentation](https://kubebuilder.io/reference/rescaffold). |
| 280 | + |
| 281 | +This command allows users to manually re-scaffold a project, to allow users add their code on top. |
| 282 | +It confirms the technical capability of regenerating and updating scaffolds effectively. |
| 283 | + |
| 284 | +This proposal builds upon this foundation by automating the process. The proposed tool would extend this functionality |
| 285 | +to automatically update projects with new scaffold versions, preserving customizations. |
| 286 | + |
| 287 | +The three-way merge approach is a common strategy for integrating changes from multiple sources. |
| 288 | +It is widely used in version control systems to combine changes from a common ancestor with two sets of modifications. |
| 289 | +In the context of this proposal, the three-way merge would combine the original scaffold, the updated scaffold, and the user’s custom code |
| 290 | +seems to be very promising. |
| 291 | + |
| 292 | +## Drawbacks |
| 293 | + |
| 294 | +- **Frequent Conflicts:** Automated updates may often result in conflicts, making the process cumbersome for users. |
| 295 | +- **Complex Resolutions:** If conflicts are hard to review and resolve, users may find the solution impractical. |
| 296 | +- **Maintenance Overhead:** The implementation could become too complex for maintainers to develop and support effectively. |
| 297 | + |
| 298 | +## Alternatives |
| 299 | + |
| 300 | +- **Manual Update Workflow**: Continue with manual updates where users regenerate |
| 301 | +and merge changes independently, though this is time-consuming and error-prone. |
| 302 | +- **Use alpha generate command**: Continue with updates partial automated provided |
| 303 | +by the alpha generate command. |
| 304 | +- **Dependabot Integration**: Leverage Dependabot for dependency updates, though this |
| 305 | +doesn’t fully support scaffold updates and could lead to incomplete upgrades. |
0 commit comments