Skip to content

Commit 6652b19

Browse files
committed
Use the build-cache.json configuration instead of a separate file
1 parent dc5f5e0 commit 6652b19

File tree

4 files changed

+155
-20
lines changed

4 files changed

+155
-20
lines changed

libraries/rush-lib/assets/rush-init/common/config/rush/build-cache.json

+43
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,48 @@
9696
* If set to true, allow writing to the cache. Defaults to false.
9797
*/
9898
// "isCacheWriteAllowed": true
99+
},
100+
101+
/**
102+
* Use this configuration with "cacheProvider"="http"
103+
*/
104+
"httpConfiguration": {
105+
/**
106+
* (Required) The URL of the server that stores the caches.
107+
* Example: "https://build-cacches.example.com/"
108+
*/
109+
// "url": "https://build-cacches.example.com/",
110+
111+
/**
112+
* (Optional) The HTTP method to use when writing to the cache (defaults to PUT).
113+
* Should be one of PUT, POST, or PATCH.
114+
* Example: "PUT"
115+
*/
116+
// "uploadMethod": "PUT",
117+
118+
/**
119+
* (Optional) HTTP headers to pass to the cache server.
120+
* Example: { "X-HTTP-Company-Id": "109283" }
121+
*/
122+
// "headers": {},
123+
124+
/**
125+
* (Optional) Shell command that prints the authorization token needed to communicate with the
126+
* cache server, and exits with exit code 0. This command will be executed from the root of
127+
* the monorepo.
128+
* Example: { "exec": "node", "args": ["common/scripts/auth.js"] }
129+
*/
130+
// "tokenHandler": { "exec": "node", "args": ["common/scripts/auth.js"] },
131+
132+
/**
133+
* (Optional) Prefix for cache keys.
134+
* Example: "my-company-"
135+
*/
136+
// "cacheKeyPrefix": "",
137+
138+
/**
139+
* (Optional) If set to true, allow writing to the cache. Defaults to false.
140+
*/
141+
// "isCacheWriteAllowed": true
99142
}
100143
}

libraries/rush-lib/src/schemas/build-cache.schema.json

+71-1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,56 @@
8585
"description": "If set to true, allow writing to the cache. Defaults to false."
8686
}
8787
}
88+
},
89+
"httpConfiguration": {
90+
"type": "object",
91+
"additionalProperties": false,
92+
"properties": {
93+
"url": {
94+
"type": "string",
95+
"description": "(Required) The URL of the server that stores the caches (e.g. \"https://build-caches.example.com\").",
96+
"format": "uri"
97+
},
98+
"uploadMethod": {
99+
"type": "string",
100+
"description": "(Optional) The HTTP method to use when writing to the cache (defaults to PUT).",
101+
"enum": ["PUT", "POST", "PATCH"],
102+
"default": "PUT"
103+
},
104+
"headers": {
105+
"type": "object",
106+
"description": "(Optional) HTTP headers to pass to the cache server",
107+
"properties": {},
108+
"additionalProperties": {
109+
"type": "string"
110+
}
111+
},
112+
"tokenHandler": {
113+
"type": "object",
114+
"description": "(Optional) Shell command that prints the authorization token needed to communicate with the HTTPS server and exits with code 0. This command will be executed from the root of the monorepo.",
115+
"properties": {
116+
"exec": {
117+
"type": "string",
118+
"description": "(Required) The command or script to execute."
119+
},
120+
"args": {
121+
"type": "array",
122+
"description": "(Optional) Arguments to pass to the command or script.",
123+
"items": {
124+
"type": "string"
125+
}
126+
}
127+
}
128+
},
129+
"cacheKeyPrefix": {
130+
"type": "string",
131+
"description": "(Optional) prefix for cache keys."
132+
},
133+
"isCacheWriteAllowed": {
134+
"type": "boolean",
135+
"description": "(Optional) If set to true, allow writing to the cache. Defaults to false."
136+
}
137+
}
88138
}
89139
},
90140
"oneOf": [
@@ -94,7 +144,7 @@
94144
"properties": {
95145
"cacheProvider": {
96146
"type": "string",
97-
"pattern": "^(?:(?!azure-blob-storage|amazon-s3).)*$"
147+
"pattern": "^(?:(?!azure-blob-storage|amazon-s3|http).)*$"
98148
}
99149
}
100150
},
@@ -160,6 +210,26 @@
160210
]
161211
}
162212
}
213+
},
214+
{
215+
"type": "object",
216+
"additionalProperties": true,
217+
"properties": {
218+
"cacheProvider": {
219+
"type": "string",
220+
"enum": ["http"]
221+
},
222+
"httpConfiguration": {
223+
"type": "object",
224+
"additionalProperties": true,
225+
"required": ["url"],
226+
"properties": {
227+
"url": {
228+
"$ref": "#/definitions/anything"
229+
}
230+
}
231+
}
232+
}
163233
}
164234
]
165235
}

rush-plugins/rush-http-build-cache-plugin/README.md

+33-11
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,49 @@ To use the HTTP build cache plugin, enable it in `common/config/rush/build-cache
1616
}
1717
```
1818

19-
Once enabled, configure the HTTP build cache in config file `common/config/rush-plugins/rush-http-build-cache-plugin.json`:
19+
Then customize the `httpConfiguration` block. For typical use cases, where you'll use a remote HTTP URL with authentication, you'll need to provide at least the `url` and `tokenHandler` options:
2020

2121
```json
2222
{
23-
"url": "https://build-cache.example.com",
24-
"tokenHandler": "node common/scripts/custom-script-that-returns-an-authentication-header.js",
25-
"isCacheWriteAllowed": false
23+
"httpConfiguration": {
24+
"url": "https://build-cache.example.com",
25+
"tokenHandler": {
26+
"exec": "node",
27+
"args": ["common/scripts/custom-script-that-returns-an-authentication-header.js"]
28+
},
29+
"isCacheWriteAllowed": false
30+
}
2631
}
2732
```
2833

29-
- `url`: The server to store cache objects.
30-
- `tokenHandler`: A script that can print the Authorization header expected by the server. The value printed to `stdout` by this command should be an exact header, for example, `Bearer ab98d8c878d937290d979a9097c90dfffff` or `Basic 098abc7dff==`.
31-
- `isCacheWriteAllowed`: A flag that determines if the plugin should write to the cache.
34+
(For more detail on the above properties and additional optional properties, consult the default `build-cache.json` file.)
35+
36+
## Authorization Details
37+
38+
The HTTP build cache plugin offloads authorization to an external executable script that you define. A typical use case would be to create a simple script, for example `common/scripts/cache-auth.js`, that prints an Authorization header value when executed.
39+
40+
For example:
41+
42+
```console
43+
node common/scripts/cache-auth.js
44+
# => Bearer 0284357923592790DDb979dBcd2zz
45+
```
46+
47+
How the script generates authorization values is up to you, and depends on the configuration of your remote cache server.
48+
49+
Possible implementations:
50+
51+
- The script could read simple environment variables (`CACHE_USER` and `CACHE_TOKEN`) defined by the developer
52+
- It could reuse existing credentials your developers have, like NPM tokens, GitHub credentials, or jFrog API tokens
53+
- It could make an HTTP call to another server accessible by your developers that returns temporary credentials
3254

3355
## HTTP Cache Server Requirements
3456

3557
The HTTP build cache plugin can use almost any HTTP/HTTPS backend for remote caching, as long as it honors the following rules:
3658

3759
- Uses `Authorization: Bearer xxx` or `Authorization: Basic xxx` headers for authentication.
3860
- Accepts GET requests for cache reads.
39-
- Accepts PUT requests for cache writes (with a raw request body -- no `form/multipart`).
61+
- Accepts PUT requests for cache writes (with a raw request body -- no `form/multipart` MIME types).
4062
- Cache hits return HTTP 200 with the file in the response body.
4163
- Successful cache writes return HTTP 2xx (200-299).
4264
- Cache misses return HTTP 404 or HTTP 403.
@@ -56,13 +78,13 @@ First, start up and configure your build cache node locally:
5678
- Enter the temporary username/password credentials printed in the startup banner
5779
- Click Build Cache > Settings > Cache Access Control and grant "Read & write" access to Anonymous
5880

59-
Second, create your `rush-http-build-cache-plugin.json` file as described in the Configuration section:
81+
Second, configure your `build-cache.json` file as described in the Configuration section:
6082

61-
- Note that your `url` should end with `/cache/`, for example, `http://localhost:5071/cache/`
83+
- Note that your `url` must end with `/cache/`, for example, `http://localhost:5071/cache/`.
6284
- To test reading and writing, set `isCacheWriteAllowed: true`.
6385
- Configure `tokenHandler` to point to a script that prints a Basic or Bearer Authorization value (this can be a dummy string if you granted Read and Write to Anonymous in your build cache node configuration).
6486

65-
Note that the Gradle Build Cache Server has a stricter format for its cache keys (they should be a simple hexadecimal hash with no non-alphanumeric characters). Configure this setting in your `common/config/rush/build-cache.json` file:
87+
Note that the Gradle Build Cache Server has a stricter format for its cache keys (they should be a simple hexadecimal hash with no non-alphanumeric characters). Configure this setting in your `build-cache.json` file:
6688

6789
```json
6890
{

rush-plugins/rush-http-build-cache-plugin/src/RushHttpBuildCachePlugin.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const PLUGIN_NAME: string = 'HttpBuildCachePlugin';
1212
/**
1313
* @public
1414
*/
15-
export interface IRushHttpBuildCachePluginOptions {
15+
export interface IRushHttpBuildCachePluginConfig {
1616
/**
1717
* The URL of the server that stores the caches (e.g. "https://build-caches.example.com").
1818
*/
@@ -53,19 +53,19 @@ export interface IRushHttpBuildCachePluginOptions {
5353
*/
5454
export class RushHttpBuildCachePlugin implements IRushPlugin {
5555
public readonly pluginName: string = PLUGIN_NAME;
56-
private readonly _options: IRushHttpBuildCachePluginOptions;
57-
58-
public constructor(options: IRushHttpBuildCachePluginOptions) {
59-
this._options = options;
60-
}
6156

6257
public apply(rushSession: RushSession, rushConfig: RushConfiguration): void {
6358
rushSession.hooks.initialize.tap(this.pluginName, () => {
6459
rushSession.registerCloudBuildCacheProviderFactory(
6560
'http',
6661
(buildCacheConfig): HttpBuildCacheProvider => {
67-
const { url, uploadMethod, headers, tokenHandler, cacheKeyPrefix, isCacheWriteAllowed } =
68-
this._options;
62+
const config: IRushHttpBuildCachePluginConfig = (
63+
buildCacheConfig as typeof buildCacheConfig & {
64+
httpConfiguration: IRushHttpBuildCachePluginConfig;
65+
}
66+
).httpConfiguration;
67+
68+
const { url, uploadMethod, headers, tokenHandler, cacheKeyPrefix, isCacheWriteAllowed } = config;
6969

7070
const options: IHttpBuildCacheProviderOptions = {
7171
pluginName: this.pluginName,

0 commit comments

Comments
 (0)