Skip to content

Commit 74e5507

Browse files
frostebiteclaude
andcommitted
Add custom providers documentation for the plugin system
Document how to use custom providers via GitHub repos, NPM packages, or local paths. Covers the ProviderInterface, supported source formats, caching behavior, and a full example implementation. Also updates the API reference to mention custom providers under providerStrategy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ac82742 commit 74e5507

2 files changed

Lines changed: 185 additions & 2 deletions

File tree

β€Ždocs/03-github-orchestrator/04-api-reference.mdxβ€Ž

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ attempt to read them from current directory's git repo (e.g branch, commit SHA,
9090
providerStrategy
9191
```
9292

93-
Specifies the Cloud Provider to use for Orchestrator jobs. Accepted values: `aws`, `k8s`,
94-
`local-docker`, `local`.
93+
Specifies the Cloud Provider to use for Orchestrator jobs. Built-in values: `aws`, `k8s`,
94+
`local-docker`, `local`. You can also specify a custom provider via GitHub URL, NPM package, or
95+
local path (see [Custom Providers](advanced-topics/custom-providers)).
9596

9697
```bash
9798
- containerCpu
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Custom Providers
2+
3+
Orchestrator uses a plugin system that lets you extend it with custom providers. A **provider** is a
4+
pluggable backend that controls where and how your builds run. Built-in providers include `aws`,
5+
`k8s`, `local-docker`, and `local`.
6+
7+
With custom providers, you can point `providerStrategy` at a GitHub repository, NPM package, or
8+
local path and Orchestrator will dynamically load it at runtime.
9+
10+
## Using a Custom Provider
11+
12+
Set `providerStrategy` to a provider source instead of a built-in name:
13+
14+
```yaml
15+
# GitHub repository
16+
- uses: game-ci/unity-builder@v4
17+
with:
18+
providerStrategy: 'https://github.com/your-org/my-provider'
19+
targetPlatform: StandaloneLinux64
20+
21+
# GitHub shorthand
22+
- uses: game-ci/unity-builder@v4
23+
with:
24+
providerStrategy: 'your-org/my-provider'
25+
targetPlatform: StandaloneLinux64
26+
27+
# Specific branch
28+
- uses: game-ci/unity-builder@v4
29+
with:
30+
providerStrategy: 'your-org/my-provider@develop'
31+
targetPlatform: StandaloneLinux64
32+
```
33+
34+
### Supported Source Formats
35+
36+
| Format | Example |
37+
| ------------------------------------- | -------------------------------------------------------- |
38+
| GitHub HTTPS URL | `https://github.com/user/repo` |
39+
| GitHub URL with branch | `https://github.com/user/repo/tree/main` |
40+
| GitHub URL with branch and path | `https://github.com/user/repo/tree/main/src/my-provider` |
41+
| GitHub shorthand | `user/repo` |
42+
| GitHub shorthand with branch | `user/repo@develop` |
43+
| GitHub shorthand with branch and path | `user/repo@develop/src/my-provider` |
44+
| GitHub SSH | `git@github.com:user/repo.git` |
45+
| NPM package | `my-provider-package` |
46+
| Scoped NPM package | `@scope/my-provider` |
47+
| Local relative path | `./my-local-provider` |
48+
| Local absolute path | `/path/to/provider` |
49+
50+
## Creating a Custom Provider
51+
52+
A provider is a module that exports a class implementing the `ProviderInterface`. The module must
53+
have an entry point at one of: `index.js`, `index.ts`, `src/index.js`, `src/index.ts`,
54+
`lib/index.js`, `lib/index.ts`, or `dist/index.js`.
55+
56+
### Required Methods
57+
58+
Every provider must implement these 7 methods:
59+
60+
```typescript
61+
interface ProviderInterface {
62+
setupWorkflow(
63+
buildGuid: string,
64+
buildParameters: BuildParameters,
65+
branchName: string,
66+
defaultSecretsArray: {
67+
ParameterKey: string;
68+
EnvironmentVariable: string;
69+
ParameterValue: string;
70+
}[],
71+
): Promise<void>;
72+
73+
runTaskInWorkflow(
74+
buildGuid: string,
75+
image: string,
76+
commands: string,
77+
mountdir: string,
78+
workingdir: string,
79+
environment: OrchestratorEnvironmentVariable[],
80+
secrets: OrchestratorSecret[],
81+
): Promise<string>;
82+
83+
cleanupWorkflow(
84+
buildParameters: BuildParameters,
85+
branchName: string,
86+
defaultSecretsArray: {
87+
ParameterKey: string;
88+
EnvironmentVariable: string;
89+
ParameterValue: string;
90+
}[],
91+
): Promise<void>;
92+
93+
garbageCollect(
94+
filter: string,
95+
previewOnly: boolean,
96+
olderThan: Number,
97+
fullCache: boolean,
98+
baseDependencies: boolean,
99+
): Promise<string>;
100+
101+
listResources(): Promise<ProviderResource[]>;
102+
listWorkflow(): Promise<ProviderWorkflow[]>;
103+
watchWorkflow(): Promise<string>;
104+
}
105+
```
106+
107+
### Example Implementation
108+
109+
```typescript
110+
// index.ts
111+
export default class MyProvider {
112+
constructor(private buildParameters: any) {}
113+
114+
async setupWorkflow(buildGuid, buildParameters, branchName, defaultSecretsArray) {
115+
// Initialize your build environment
116+
}
117+
118+
async runTaskInWorkflow(buildGuid, image, commands, mountdir, workingdir, environment, secrets) {
119+
// Execute the build task in your environment
120+
return 'Build output';
121+
}
122+
123+
async cleanupWorkflow(buildParameters, branchName, defaultSecretsArray) {
124+
// Tear down resources after the build
125+
}
126+
127+
async garbageCollect(filter, previewOnly, olderThan, fullCache, baseDependencies) {
128+
// Clean up old resources
129+
return 'Garbage collection complete';
130+
}
131+
132+
async listResources() {
133+
// Return active resources
134+
return [];
135+
}
136+
137+
async listWorkflow() {
138+
// Return running workflows
139+
return [];
140+
}
141+
142+
async watchWorkflow() {
143+
// Stream logs from a running workflow
144+
return '';
145+
}
146+
}
147+
```
148+
149+
## How It Works
150+
151+
When `providerStrategy` is set to a value that doesn't match a built-in provider name, Orchestrator
152+
will:
153+
154+
1. **Detect the source type** β€” GitHub URL, NPM package, or local path.
155+
2. **Fetch the provider** β€” For GitHub repos, the repository is cloned (shallow, depth 1) into a
156+
`.provider-cache/` directory. Cached repos are automatically updated on subsequent runs.
157+
3. **Load the module** β€” The entry point is imported and the default export is used.
158+
4. **Validate the interface** β€” All 7 required methods are checked. If any are missing, loading
159+
fails.
160+
5. **Fallback** β€” If loading fails for any reason, Orchestrator logs the error and falls back to the
161+
local provider so your pipeline doesn't break.
162+
163+
## Caching
164+
165+
GitHub repositories are cached in the `.provider-cache/` directory, keyed by owner, repo, and
166+
branch. On subsequent runs the loader checks for updates and pulls them automatically.
167+
168+
### Environment Variables
169+
170+
| Variable | Default | Description |
171+
| -------------------- | ----------------- | --------------------------------------- |
172+
| `PROVIDER_CACHE_DIR` | `.provider-cache` | Custom cache directory for cloned repos |
173+
| `GIT_TIMEOUT` | `30000` | Git operation timeout in milliseconds |
174+
175+
## Best Practices
176+
177+
- **Pin a branch or tag** β€” Use `user/repo@v1.0` or a specific branch to avoid unexpected changes.
178+
- **Test locally first** β€” Use a local path during development before publishing.
179+
- **Handle errors gracefully** β€” Your provider methods should throw clear errors so Orchestrator can
180+
log them and fall back if needed.
181+
- **Keep it lightweight** β€” The provider module is loaded at runtime. Minimize dependencies to keep
182+
startup fast.

0 commit comments

Comments
Β (0)