Runner Scripts
You can use runner scripts to define the core execution logic that Code Genie runs inside a dev container when a pull request is created or updated.
When Code Genie triggers a container, it runs
a command string defined in code-config.jsonc via the
custom-commands or coding-command properties. The
command string invokes the runner script, which executes the task, processes the
results, and generates the structured JSON output that Code Genie reads to post PR
comments and decide on approval or rejection.
The default Code Genie configuration includes built-in runner scripts that you cannot access or modify. You can use the information in this topic to create your own runner script for custom use cases, such as running unit tests or performing static code analysis.
The following table lists the built-in runner scripts used in the default Code Genie configuration:
| Script | Type | Purpose |
|---|---|---|
| run-trivy.sh | Shell script | Runs Trivy security scanning on the PR source branch and outputs findings to the result JSON file. |
| run-copilot.ts | TypeScript script | Invokes GitHub Copilot to implement work items or perform AI code reviews on PRs. |
| run-bob.ts | TypeScript script | Invokes IBM Bob to implement work items or perform AI code reviews on PRs. |
You can write your own runner script in any language that the dev container supports. For a step-by-step walkthrough of creating a custom runner script, see DevOps Loop: Automated JUnit Testing with Code Genie.
What a Runner Script Does
Regardless of the use case, a runner script performs the following functions:
- Executes the core task, such as performing a security scan, invoking an AI code review, or running tests.
- Generates a structured JSON result file that Code Genie reads to post PR comments and determine approval or rejection.
Creating a Custom Runner Script
To create a custom runner script, you must embed the script into the dev container image and ensure that the command in code-config.jsonc passes the inputs that the script expects.
Embedding the script in the dev container: You can embed a runner script into
the dev container image at build time by using the COPY instruction
in the Dockerfile, followed by chmod +x to make it executable.
The following Dockerfile shows a minimal example that
embeds a JUnit runner script into the dev container
image:
FROM registry.access.redhat.com/ubi9
# Install Java, Maven, Git, and JQ in a single layer
RUN dnf install -y --allowerasing --setopt=install_weak_deps=False \
git java-17-openjdk java-17-openjdk-devel maven jq && dnf clean all
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# Configure non-root user and directories
RUN useradd -u 1001 -m codeuser && \
mkdir -p /opt /tmp/junit-results && \
chown -R 1001:1001 /opt /tmp/junit-results /home/codeuser
COPY run-junit.sh /opt/run-junit.sh
RUN chmod +x /opt/run-junit.sh
USER 1001
WORKDIR /home/codeuser
CMD ["/bin/bash"]
The script is then available inside the container at a known path. The command in code-config.jsonc copies it to the working directory before executing it. Because the Dockerfile bakes the script into the image, the container image and the command string are tightly coupled, the image determines what scripts are available, and the configuration determines how it invokes them. Any mismatch between the two causes the automation to fail. For more information, see Creating Dev Containers using a Dockerfile.
Mapping commands to script expectations: The commands in code-config.jsonc must map directly to what the runner script expects. Common inputs include:
${code-folder}: The working directory inside the container where Code Genie clones the repository and executes commands.${result-json}: The target path where the script writes its execution summary in JSON format for Code Genie to parse.- Use-case specific flags: Such as rejection thresholds or tool-specific arguments that control how the script evaluates results and determines PR approval or rejection.
The following code-config.jsonc shows how the Trivy runner script is invoked, with the required inputs passed as part of the command string:
{
"code-genie": {
"pull-request": {
"dev-container": "TrivyScan",
"custom-commands": [
{
"run-trivy": "cp /opt/run-trivy.sh /usr/code/ && \
chmod +x /usr/code/run-trivy.sh && \
REPO_URL=https://${platform-fqdm}/control/${repo-owner}/${repo}/src/branch/${pr-branch}/ \
/usr/code/run-trivy.sh ${code-folder} ${result-json} \
--reject=high \
--trivyArgs=\"--scanners vuln,misconfig,secret,license --license-full --severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL\""
}
]
}
}
}