feat: add Rundeck Runner support and repository-named subdirectories#44
feat: add Rundeck Runner support and repository-named subdirectories#44elioe wants to merge 3 commits into
Conversation
elioe
commented
May 20, 2026
- Implement ProxyRunnerPlugin and ProxySecretBundleCreator for secure distributed execution.
- Add gitUseRepoNameSubdirectory option to clone under base directory using the git repo name.
- Clean up temporary SSH keys on factory close and fix hard reset behavior in GitManager.
- Add Spock unit tests for secret bundling and repo name extraction.
- Implement ProxyRunnerPlugin and ProxySecretBundleCreator for secure distributed execution. - Add gitUseRepoNameSubdirectory option to clone under base directory using the git repo name. - Clean up temporary SSH keys on factory close and fix hard reset behavior in GitManager. - Add Spock unit tests for secret bundling and repo name extraction.
There was a problem hiding this comment.
Pull request overview
This PR adds Rundeck Runner compatibility to the Git workflow steps by implementing runner/secret-bundling interfaces, introduces an option to clone into a repository-named subdirectory under the configured base directory, and improves SSH key lifecycle management by explicitly closing/deleting temporary key material after JGit transport operations.
Changes:
- Implement
ProxyRunnerPlugin+ProxySecretBundleCreatorfor Git Clone/Commit/Push steps, backed by new secret path/bundle helpers inGitPluginUtil. - Add
gitUseRepoNameSubdirectoryoption and repo-name extraction utility (extractRepoName) to support repository-named clone directories. - Improve JGit SSH transport cleanup by making
PluginSshSessionFactoryCloseableand ensuring factories are closed after clone/pull/push; add Spock tests for secret bundling, repo name extraction, and SSH temp key cleanup.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/groovy/com/rundeck/plugin/util/GitPluginUtil.groovy | Adds repo name extraction and shared secret-path/secret-bundle helpers for Runner support. |
| src/main/groovy/com/rundeck/plugin/GitCloneWorkflowStep.groovy | Adds Runner interfaces, repo-name subdir option handling, and secret bundle/path delegation. |
| src/main/groovy/com/rundeck/plugin/GitCommitWorkflowStep.groovy | Adds Runner interfaces, repo-name subdir option handling, and secret bundle/path delegation. |
| src/main/groovy/com/rundeck/plugin/GitPushWorkflowStep.groovy | Adds Runner interfaces, repo-name subdir option handling, and secret bundle/path delegation. |
| src/main/groovy/com/rundeck/plugin/util/PluginSshSessionFactory.groovy | Makes SSH session factory reusable/closeable and deletes temp key files on close. |
| src/main/groovy/com/rundeck/plugin/GitManager.groovy | Adds hard reset/clean before pull and ensures SSH factories are closed after operations. |
| src/test/groovy/com/rundeck/plugin/WorkflowStepSecretBundleSpec.groovy | Tests workflow steps implement runner/secret-bundle interfaces and return/bundle secrets correctly. |
| src/test/groovy/com/rundeck/plugin/util/GitPluginUtilSecretBundleSpec.groovy | Unit tests for secret-path resolution and secret bundle preparation behavior. |
| src/test/groovy/com/rundeck/plugin/util/GitPluginUtilExtractRepoNameSpec.groovy | Parameterized tests for extracting repo names from various Git URL formats. |
| src/test/groovy/com/rundeck/plugin/util/PluginSshSessionFactorySpec.groovy | Updates behavior expectation (factory reuse) and adds tests for idempotent close + temp key deletion. |
Comments suppressed due to low confidence (1)
src/main/groovy/com/rundeck/plugin/GitManager.groovy:209
- The success/failure logging here is incorrect: the
elsebranch logs the same "not successful" message as the failure branch. This makes logs misleading during normal successful pulls.
if (!result.isSuccessful()) {
logger.info("Pull is not successful.")
} else {
logger.debug("Pull is not successful.")
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static String extractRepoName(String gitUrl) { | ||
| if (!gitUrl) return null | ||
| String cleaned = gitUrl.replaceAll('/+$', '') | ||
| int lastSlash = cleaned.lastIndexOf('/') | ||
| int lastColon = cleaned.lastIndexOf(':') | ||
| int lastSep = Math.max(lastSlash, lastColon) | ||
| String name = lastSep >= 0 ? cleaned.substring(lastSep + 1) : cleaned | ||
| if (name.endsWith('.git')) { | ||
| name = name.substring(0, name.length() - 4) | ||
| } | ||
| return name ?: null | ||
| } |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/main/groovy/com/rundeck/plugin/GitManager.groovy:209
- The pull result logging is incorrect: the
elsebranch logs "Pull is not successful." even whenresult.isSuccessful()is true, which will mislead users and make troubleshooting harder.
if (!result.isSuccessful()) {
logger.info("Pull is not successful.")
} else {
logger.debug("Pull is not successful.")
}
| sshFactory = setupTransportAuthentication(sshConfig, pushCommand, this.gitURL) | ||
| def results = withPluginClassLoader { pushCommand.call() } | ||
| def updates = results.collectMany { it.remoteUpdates ?: [] } | ||
| def failed = updates.findAll { it.status != RemoteRefUpdate.Status.OK } |
| @Override | ||
| void close() { | ||
| if (sessionFactory != null) { | ||
| try { | ||
| sessionFactory.close() | ||
| } catch (Exception ignored) { | ||
| } | ||
| sessionFactory.deleteTempKey() | ||
| sessionFactory = null | ||
| } | ||
| } |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>