@effected/github-actions 0.23.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Action.js +1 -2
- package/ActionCache.js +1 -2
- package/ActionEnvironment.js +7 -10
- package/ActionInput.js +15 -19
- package/ActionLogger.js +1 -2
- package/ActionOutputs.js +1 -2
- package/ActionState.js +1 -2
- package/ActionsIdentityToken.js +6 -7
- package/ActionsProvenance.js +18 -17
- package/Artifact.js +4 -4
- package/BlobEnvelope.js +1 -2
- package/BlobStore.githubCache.js +1 -2
- package/BlobStore.js +59 -30
- package/BlobTransfer.js +1 -2
- package/CacheKey.js +1 -2
- package/CheckDocument.js +1 -2
- package/CheckState.js +1 -2
- package/ChildEnv.js +1 -2
- package/DetachedProcess.js +1 -2
- package/DryRun.js +1 -2
- package/GitHubMarkdown.js +1 -2
- package/GitHubToken.js +1 -2
- package/ManagedDocument.js +1 -2
- package/OidcTokenIssuer.js +24 -54
- package/PackageManagerInstaller.js +20 -24
- package/README.md +3 -3
- package/Secret.js +11 -8
- package/ToolInstaller.js +4 -4
- package/index.d.ts +51 -125
- package/index.js +2 -2
- package/internal/actionsResults.js +6 -6
- package/internal/archiveCommands.js +1 -2
- package/internal/cacheService.js +1 -2
- package/internal/digest.js +1 -2
- package/internal/fsProbe.js +1 -2
- package/internal/json.js +11 -0
- package/internal/pnpmExe.js +1 -2
- package/internal/runner.js +22 -3
- package/internal/runnerFile.js +1 -2
- package/internal/shim.js +1 -2
- package/internal/spawn.js +1 -2
- package/internal/twirp.js +1 -2
- package/internal/unstubbed.js +1 -2
- package/package.json +13 -10
- package/internal/jwt.js +0 -42
- package/internal/sigv4.js +0 -115
package/Action.js
CHANGED
|
@@ -8,7 +8,7 @@ import { NodeServices } from "@effect/platform-node";
|
|
|
8
8
|
import { Cause, Effect, Exit, Layer, LogLevel, Option, References, Result } from "effect";
|
|
9
9
|
import { FetchHttpClient } from "effect/http";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// src/Action.ts
|
|
12
12
|
/**
|
|
13
13
|
* The default runtime an action executes inside.
|
|
14
14
|
*
|
|
@@ -152,5 +152,4 @@ var Action = class {
|
|
|
152
152
|
};
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
-
//#endregion
|
|
156
155
|
export { Action, ActionRuntime, describeCause };
|
package/ActionCache.js
CHANGED
|
@@ -13,7 +13,7 @@ import { BlobClient, BlockBlobClient } from "@azure/storage-blob";
|
|
|
13
13
|
import { GlobPattern, GlobSet } from "@effected/glob";
|
|
14
14
|
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// src/ActionCache.ts
|
|
17
17
|
/**
|
|
18
18
|
* Raised when the runner's cache cannot be read or written.
|
|
19
19
|
*
|
|
@@ -379,5 +379,4 @@ var ActionCache = class ActionCache extends Context.Service()("@effected/github-
|
|
|
379
379
|
static layerTest = (overrides = {}) => Layer.succeed(ActionCache, ActionCache.makeTest(overrides));
|
|
380
380
|
};
|
|
381
381
|
|
|
382
|
-
//#endregion
|
|
383
382
|
export { ActionCache, ActionCacheError };
|
package/ActionEnvironment.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { decodeJson } from "./internal/json.js";
|
|
1
2
|
import { Context, Effect, FileSystem, Layer, Option, Schema } from "effect";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
// src/ActionEnvironment.ts
|
|
4
5
|
/**
|
|
5
6
|
* Raised when the runner environment does not say what an action needs.
|
|
6
7
|
*
|
|
@@ -176,14 +177,11 @@ const make = (base) => Effect.gen(function* () {
|
|
|
176
177
|
name: "GITHUB_EVENT_PATH",
|
|
177
178
|
detail: `could not read "${path}": ${String(cause)}`
|
|
178
179
|
})));
|
|
179
|
-
return yield* Effect.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
detail: `not valid JSON: ${String(cause)}`
|
|
185
|
-
})
|
|
186
|
-
});
|
|
180
|
+
return yield* decodeJson(raw).pipe(Effect.mapError((cause) => new ActionEnvironmentError({
|
|
181
|
+
reason: "malformed",
|
|
182
|
+
name: "GITHUB_EVENT_PATH",
|
|
183
|
+
detail: `not valid JSON: ${cause.message}`
|
|
184
|
+
})));
|
|
187
185
|
}),
|
|
188
186
|
withEnv: (overrides, effect) => Effect.flatMap(EnvOverrides, (current) => Effect.provideService(effect, EnvOverrides, {
|
|
189
187
|
...current,
|
|
@@ -324,5 +322,4 @@ var ActionEnvironment = class ActionEnvironment extends Context.Service()("@effe
|
|
|
324
322
|
static layerTest = (overrides = {}, payload) => Layer.effect(ActionEnvironment, ActionEnvironment.makeTest(overrides, payload)).pipe(Layer.provide(FileSystem.layerNoop({})));
|
|
325
323
|
};
|
|
326
324
|
|
|
327
|
-
//#endregion
|
|
328
325
|
export { ActionEnvironment, ActionEnvironmentError, GitHubContext, RunnerContext };
|
package/ActionInput.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { decodeJson } from "./internal/json.js";
|
|
1
2
|
import { Config, ConfigProvider, Context, Effect, Schema, SchemaIssue } from "effect";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
// src/ActionInput.ts
|
|
4
5
|
/**
|
|
5
6
|
* The variable name the runner publishes an input under.
|
|
6
7
|
*
|
|
@@ -29,7 +30,17 @@ const inputVariable = (name) => `INPUT_${name.replaceAll(" ", "_").toUpperCase()
|
|
|
29
30
|
* mutations the author meant to rehearse. `actual` carries the offending value
|
|
30
31
|
* so the rendered error names it.
|
|
31
32
|
*/
|
|
32
|
-
|
|
33
|
+
/**
|
|
34
|
+
* A `ConfigError` carrying `message` as its first issue and, when a decode
|
|
35
|
+
* failed, that decode's own issue beside it, so the cause is structured
|
|
36
|
+
* rather than flattened into the message.
|
|
37
|
+
*/
|
|
38
|
+
const configError = (message, actual, cause) => {
|
|
39
|
+
const stated = new SchemaIssue.InvalidValue({ message }, actual);
|
|
40
|
+
return new Config.ConfigError(new Schema.SchemaError(cause === void 0 ? stated : new SchemaIssue.Composite(Schema.Unknown.ast, [stated, cause.issue], actual)));
|
|
41
|
+
};
|
|
42
|
+
/** The JSON-array form of {@link ActionInput.list}. */
|
|
43
|
+
const decodeStringArray = Schema.decodeUnknownEffect(Schema.Array(Schema.String));
|
|
33
44
|
/** YAML 1.2 core-schema booleans, which is what the runner documents. */
|
|
34
45
|
const TRUE = /* @__PURE__ */ new Set([
|
|
35
46
|
"true",
|
|
@@ -267,13 +278,7 @@ var ActionInput = class ActionInput {
|
|
|
267
278
|
return Config.String(inputVariable(name)).pipe(Config.mapEffect((raw) => {
|
|
268
279
|
const trimmed = raw.trim();
|
|
269
280
|
if (trimmed === "") return Effect.succeed([]);
|
|
270
|
-
if (trimmed.startsWith("["))
|
|
271
|
-
const parsed = JSON.parse(trimmed);
|
|
272
|
-
if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) return Effect.succeed(parsed);
|
|
273
|
-
return Effect.fail(configError(`Input "${name}" is a JSON array but not an array of strings`, raw));
|
|
274
|
-
} catch {
|
|
275
|
-
return Effect.fail(configError(`Input "${name}" looks like JSON but could not be parsed`, raw));
|
|
276
|
-
}
|
|
281
|
+
if (trimmed.startsWith("[")) return decodeJson(trimmed).pipe(Effect.mapError((cause) => configError(`Input "${name}" looks like JSON but could not be parsed`, raw, cause)), Effect.flatMap((parsed) => decodeStringArray(parsed).pipe(Effect.mapError((cause) => configError(`Input "${name}" is a JSON array but not an array of strings`, raw, cause)))));
|
|
277
282
|
const entries = trimmed.split(/[\n,]/).map((item) => item.trim()).filter((item) => !item.startsWith("#")).map((item) => item.startsWith("- ") || item.startsWith("* ") ? item.slice(2).trim() : item).filter((item) => item !== "");
|
|
278
283
|
return Effect.succeed(entries);
|
|
279
284
|
}));
|
|
@@ -332,15 +337,7 @@ var ActionInput = class ActionInput {
|
|
|
332
337
|
* which is exactly the missing-versus-malformed split above.
|
|
333
338
|
*/
|
|
334
339
|
static schema(name, schema) {
|
|
335
|
-
return Config.String(inputVariable(name)).pipe(Config.mapEffect((raw) => {
|
|
336
|
-
let parsed;
|
|
337
|
-
try {
|
|
338
|
-
parsed = JSON.parse(raw);
|
|
339
|
-
} catch {
|
|
340
|
-
return Effect.fail(configError(`Input "${name}" is not valid JSON`, raw));
|
|
341
|
-
}
|
|
342
|
-
return Schema.decodeUnknownEffect(schema)(parsed).pipe(Effect.mapError(() => configError(`Input "${name}" did not satisfy its schema`, parsed)));
|
|
343
|
-
}));
|
|
340
|
+
return Config.String(inputVariable(name)).pipe(Config.mapEffect((raw) => decodeJson(raw).pipe(Effect.mapError((cause) => configError(`Input "${name}" is not valid JSON`, raw, cause)), Effect.flatMap((parsed) => Schema.decodeUnknownEffect(schema)(parsed).pipe(Effect.mapError((cause) => configError(`Input "${name}" did not satisfy its schema`, parsed, cause)))))));
|
|
344
341
|
}
|
|
345
342
|
/**
|
|
346
343
|
* A `ConfigProvider` over a record of runner variables **or input names**.
|
|
@@ -512,5 +509,4 @@ var ActionInput = class ActionInput {
|
|
|
512
509
|
static layerDefault = ConfigProvider.layer(Effect.map(Effect.context(), (context) => ActionInput.providerOver(Context.getOrUndefined(context, ConfigProvider.ConfigProvider) ?? ConfigProvider.fromEnv())));
|
|
513
510
|
};
|
|
514
511
|
|
|
515
|
-
//#endregion
|
|
516
512
|
export { ActionInput, inputVariable };
|
package/ActionLogger.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ActionEnvironment } from "./ActionEnvironment.js";
|
|
|
2
2
|
import { CommandNeutralizer, WorkflowCommand } from "@effected/github-commands";
|
|
3
3
|
import { Console, Context, Effect, Exit, Inspectable, Layer, LogLevel, Logger, References } from "effect";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// src/ActionLogger.ts
|
|
6
6
|
/**
|
|
7
7
|
* Render a log message, which arrives as an array of the values passed to
|
|
8
8
|
* `Effect.log*`.
|
|
@@ -223,5 +223,4 @@ var ActionLogger = class ActionLogger extends Context.Service()("@effected/githu
|
|
|
223
223
|
static layerSilent = Layer.mergeAll(ActionLogger.layerTest(), Logger.layer([]));
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
-
//#endregion
|
|
227
226
|
export { ActionLogger };
|
package/ActionOutputs.js
CHANGED
|
@@ -4,7 +4,7 @@ import { unstubbed } from "./internal/unstubbed.js";
|
|
|
4
4
|
import { CommandNeutralizer, WorkflowCommand } from "@effected/github-commands";
|
|
5
5
|
import { Console, Context, Effect, FileSystem, Layer, Schema } from "effect";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// src/ActionOutputs.ts
|
|
8
8
|
/**
|
|
9
9
|
* Raised when an action cannot publish an output.
|
|
10
10
|
*
|
|
@@ -337,5 +337,4 @@ var ActionOutputs = class ActionOutputs extends Context.Service()("@effected/git
|
|
|
337
337
|
};
|
|
338
338
|
};
|
|
339
339
|
|
|
340
|
-
//#endregion
|
|
341
340
|
export { ActionOutputs, DetachedOutputError, InvalidOutputNameError, OutputEncodeError, RecordedOutput, RunnerFileUnavailableError, RunnerFileWriteError };
|
package/ActionState.js
CHANGED
|
@@ -4,7 +4,7 @@ import { unstubbed } from "./internal/unstubbed.js";
|
|
|
4
4
|
import { ActionOutputs } from "./ActionOutputs.js";
|
|
5
5
|
import { Context, Effect, FileSystem, Layer, Option, Schema } from "effect";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// src/ActionState.ts
|
|
8
8
|
/**
|
|
9
9
|
* Raised when action state cannot be saved, read or decoded across the phase
|
|
10
10
|
* boundary.
|
|
@@ -157,5 +157,4 @@ var ActionState = class ActionState extends Context.Service()("@effected/github-
|
|
|
157
157
|
static layerTest = (overrides = {}) => Layer.succeed(ActionState, ActionState.makeTest(overrides));
|
|
158
158
|
};
|
|
159
159
|
|
|
160
|
-
//#endregion
|
|
161
160
|
export { ActionState, ActionStateError };
|
package/ActionsIdentityToken.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { OidcTokenIssuer } from "./OidcTokenIssuer.js";
|
|
2
2
|
import { Effect, Layer } from "effect";
|
|
3
|
-
import { IdentityToken, IdentityTokenError } from "@effected/
|
|
3
|
+
import { IdentityToken, IdentityTokenError } from "@effected/oidc";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
// src/ActionsIdentityToken.ts
|
|
6
6
|
/**
|
|
7
|
-
* Serves `@effected/
|
|
7
|
+
* Serves `@effected/oidc`'s `IdentityToken` contract from the runner's own OIDC
|
|
8
8
|
* token service, so signing an SBOM inside a workflow needs no further wiring.
|
|
9
9
|
*
|
|
10
10
|
* @remarks
|
|
11
|
-
* `@effected/
|
|
12
|
-
* one redacted token — precisely so that
|
|
13
|
-
*
|
|
11
|
+
* `@effected/oidc` declares `IdentityToken` — one method, one audience,
|
|
12
|
+
* one redacted token — precisely so that a consumer of a token, such as
|
|
13
|
+
* `@effected/sbom`'s signer, does not drag the Actions runtime in. This is the
|
|
14
14
|
* layer that closes the inversion from the other side: it serves that contract
|
|
15
15
|
* from the runner's own OIDC token service ({@link OidcTokenIssuer}), the same
|
|
16
16
|
* arrangement as `@effected/workspaces` implementing `@effected/commands`'
|
|
@@ -58,5 +58,4 @@ var ActionsIdentityToken = class {
|
|
|
58
58
|
}))) })));
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
//#endregion
|
|
62
61
|
export { ActionsIdentityToken };
|
package/ActionsProvenance.js
CHANGED
|
@@ -3,7 +3,7 @@ import { OidcTokenIssuer } from "./OidcTokenIssuer.js";
|
|
|
3
3
|
import { Effect, Option } from "effect";
|
|
4
4
|
import { SlsaProvenance } from "@effected/sbom";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/ActionsProvenance.ts
|
|
7
7
|
/**
|
|
8
8
|
* The server URL a workflow on github.com runs against.
|
|
9
9
|
*
|
|
@@ -20,12 +20,14 @@ const DEFAULT_SERVER_URL = "https://github.com";
|
|
|
20
20
|
*
|
|
21
21
|
* @remarks
|
|
22
22
|
* `SlsaProvenance.forGitHubWorkflow` is total and does the real work, but it
|
|
23
|
-
* takes
|
|
24
|
-
* actually holds is the runner's own OIDC claims,
|
|
25
|
-
*
|
|
26
|
-
* fields, so transposing `
|
|
27
|
-
* passes every type check, and produces a
|
|
28
|
-
* the **wrong** provenance. This module
|
|
23
|
+
* takes an all-string input record — and the only input anyone inside a
|
|
24
|
+
* workflow actually holds is the runner's own OIDC claims, decoded as
|
|
25
|
+
* `@effected/github`'s `ActionsOidcClaims` with integer ids. The projection
|
|
26
|
+
* between the two is eleven close-cousin fields, so transposing `repositoryId`
|
|
27
|
+
* and `repositoryOwnerId` compiles, passes every type check, and produces a
|
|
28
|
+
* validly signed attestation asserting the **wrong** provenance. This module
|
|
29
|
+
* owns that projection once, rendering the ids back to the decimal strings the
|
|
30
|
+
* token carried, on the same
|
|
29
31
|
* `github-actions` ↔ `sbom` seam as {@link ActionsIdentityToken}: `sbom` must
|
|
30
32
|
* not depend on the Actions runtime, so the adapter lives here, beside the
|
|
31
33
|
* services it reads.
|
|
@@ -55,7 +57,7 @@ var ActionsProvenance = class {
|
|
|
55
57
|
*
|
|
56
58
|
* @remarks
|
|
57
59
|
* Every field `GitHubWorkflowProvenance` declares is populated from
|
|
58
|
-
*
|
|
60
|
+
* the runner's `ActionsOidcClaims`, except `serverUrl`, which is read from
|
|
59
61
|
* `GITHUB_SERVER_URL` through {@link ActionEnvironment}'s `getOptional`
|
|
60
62
|
* with `https://github.com` as the default — **not** through the
|
|
61
63
|
* `GitHubContext` projection. The projection fails typed when a `GITHUB_*`
|
|
@@ -88,17 +90,16 @@ var ActionsProvenance = class {
|
|
|
88
90
|
repository: claims.repository,
|
|
89
91
|
ref: claims.ref,
|
|
90
92
|
sha: claims.sha,
|
|
91
|
-
eventName: claims.
|
|
92
|
-
workflowRef: claims.
|
|
93
|
-
jobWorkflowRef: claims.
|
|
94
|
-
repositoryId: claims.
|
|
95
|
-
repositoryOwnerId: claims.
|
|
96
|
-
runnerEnvironment: claims.
|
|
97
|
-
runId: claims.
|
|
98
|
-
runAttempt: claims.
|
|
93
|
+
eventName: claims.eventName,
|
|
94
|
+
workflowRef: claims.workflowRef,
|
|
95
|
+
jobWorkflowRef: claims.jobWorkflowRef,
|
|
96
|
+
repositoryId: String(claims.repositoryId),
|
|
97
|
+
repositoryOwnerId: String(claims.repositoryOwnerId),
|
|
98
|
+
runnerEnvironment: claims.runnerEnvironment,
|
|
99
|
+
runId: String(claims.runId),
|
|
100
|
+
runAttempt: String(claims.runAttempt)
|
|
99
101
|
});
|
|
100
102
|
});
|
|
101
103
|
};
|
|
102
104
|
|
|
103
|
-
//#endregion
|
|
104
105
|
export { ActionsProvenance };
|
package/Artifact.js
CHANGED
|
@@ -7,12 +7,12 @@ import { digestFileHex } from "./internal/digest.js";
|
|
|
7
7
|
import { isWindowsRunner } from "./internal/runner.js";
|
|
8
8
|
import { spawnOnce } from "./internal/spawn.js";
|
|
9
9
|
import { unzipCommand, zipCommand, zipManifest } from "./internal/archiveCommands.js";
|
|
10
|
-
import { Context, Effect, FileSystem, Layer, Option, Path, Result, Schema } from "effect";
|
|
10
|
+
import { Context, DateTime, Duration, Effect, FileSystem, Layer, Option, Path, Result, Schema } from "effect";
|
|
11
11
|
import { HttpClient } from "effect/http";
|
|
12
12
|
import { BlobClient, BlockBlobClient } from "@azure/storage-blob";
|
|
13
13
|
import { ChildProcessSpawner } from "effect/process";
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
// src/Artifact.ts
|
|
16
16
|
/**
|
|
17
17
|
* Raised when an artifact cannot be uploaded, listed, downloaded or deleted.
|
|
18
18
|
*
|
|
@@ -263,11 +263,12 @@ const make = (transfer) => Effect.gen(function* () {
|
|
|
263
263
|
cause
|
|
264
264
|
})));
|
|
265
265
|
const digest = yield* digestOf(packed, name);
|
|
266
|
+
const expiresAt = options?.retentionDays === void 0 ? void 0 : DateTime.formatIso(DateTime.addDuration(yield* DateTime.now, Duration.days(options.retentionDays)));
|
|
266
267
|
const finalized = yield* call("FinalizeArtifact", () => ({
|
|
267
268
|
name,
|
|
268
269
|
size: String(size.size),
|
|
269
270
|
hash: `sha256:${digest}`,
|
|
270
|
-
...
|
|
271
|
+
...expiresAt === void 0 ? {} : { expiresAt }
|
|
271
272
|
}), name);
|
|
272
273
|
if (finalized === CONFLICT || !isOk(finalized)) return yield* Effect.fail(new ArtifactError({
|
|
273
274
|
reason: "refused",
|
|
@@ -399,5 +400,4 @@ var Artifact = class Artifact extends Context.Service()("@effected/github-action
|
|
|
399
400
|
static layerTest = (overrides = {}) => Layer.succeed(Artifact, Artifact.makeTest(overrides));
|
|
400
401
|
};
|
|
401
402
|
|
|
402
|
-
//#endregion
|
|
403
403
|
export { Artifact, ArtifactError };
|
package/BlobEnvelope.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Result, Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/BlobEnvelope.ts
|
|
4
4
|
/**
|
|
5
5
|
* Raised when bytes cannot be read as an envelope.
|
|
6
6
|
*
|
|
@@ -166,5 +166,4 @@ var BlobEnvelope = class {
|
|
|
166
166
|
}
|
|
167
167
|
};
|
|
168
168
|
|
|
169
|
-
//#endregion
|
|
170
169
|
export { BlobEnvelope, BlobMetadataDecodeError, BlobMetadataEncodeError, NotABlobEnvelopeError, TruncatedBlobEnvelopeError, UnsupportedBlobEnvelopeVersionError };
|
package/BlobStore.githubCache.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Effect, Layer, Option } from "effect";
|
|
|
10
10
|
import { HttpClient } from "effect/http";
|
|
11
11
|
import { BlobClient, BlockBlobClient } from "@azure/storage-blob";
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
// src/BlobStore.githubCache.ts
|
|
14
14
|
/**
|
|
15
15
|
* The `version` every entry is filed under.
|
|
16
16
|
*
|
|
@@ -166,5 +166,4 @@ var GitHubCacheBlobStore = class {
|
|
|
166
166
|
static layerWith = (transfer) => Layer.effect(BlobStore, make(transfer));
|
|
167
167
|
};
|
|
168
168
|
|
|
169
|
-
//#endregion
|
|
170
169
|
export { GitHubCacheBlobStore };
|
package/BlobStore.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { unstubbed } from "./internal/unstubbed.js";
|
|
2
2
|
import { BlobEnvelope } from "./BlobEnvelope.js";
|
|
3
|
-
import { sign } from "./internal/sigv4.js";
|
|
4
3
|
import { Secret } from "./Secret.js";
|
|
5
|
-
import { Context, Effect, Layer, Option, Schema } from "effect";
|
|
4
|
+
import { Context, Crypto, DateTime, Effect, Layer, Option, Schema } from "effect";
|
|
6
5
|
import { HttpClient, HttpClientRequest } from "effect/http";
|
|
6
|
+
import { SigV4 } from "@effected/crypto";
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// src/BlobStore.ts
|
|
9
9
|
/**
|
|
10
10
|
* Raised when a blob cannot be stored or retrieved.
|
|
11
11
|
*
|
|
@@ -15,12 +15,17 @@ var BlobStoreError = class extends Schema.TaggedError()("BlobStoreError", {
|
|
|
15
15
|
/**
|
|
16
16
|
* `unreachable` — the store could not be contacted. `refused` — it answered,
|
|
17
17
|
* unhappily; `status` says how. `misconfigured` — the layer was built with
|
|
18
|
-
* settings the store cannot use
|
|
18
|
+
* settings the store cannot use, or a request could not be signed with them
|
|
19
|
+
* (no WebCrypto in the runtime, or key material it refuses). `invalidKey` —
|
|
20
|
+
* the caller's key cannot be stored at all, whatever the settings: on S3, a
|
|
21
|
+
* key with a `.` or `..` path segment, which no URL carries as signed.
|
|
22
|
+
* Nothing is sent.
|
|
19
23
|
*/
|
|
20
24
|
reason: Schema.Literals([
|
|
21
25
|
"unreachable",
|
|
22
26
|
"refused",
|
|
23
|
-
"misconfigured"
|
|
27
|
+
"misconfigured",
|
|
28
|
+
"invalidKey"
|
|
24
29
|
]),
|
|
25
30
|
/** The key involved. A stable identifier, never a value. */
|
|
26
31
|
key: Schema.optionalKey(Schema.String),
|
|
@@ -35,6 +40,7 @@ var BlobStoreError = class extends Schema.TaggedError()("BlobStoreError", {
|
|
|
35
40
|
switch (this.reason) {
|
|
36
41
|
case "unreachable": return `The blob store could not be reached${this.key === void 0 ? "" : ` for "${this.key}"`}`;
|
|
37
42
|
case "refused": return `The blob store refused "${this.key}"${this.status === void 0 ? "" : ` with status ${this.status}`}${this.detail === void 0 ? "" : `: ${this.detail}`}`;
|
|
43
|
+
case "invalidKey": return `The blob store cannot hold the key "${this.key}"${this.detail === void 0 ? "" : `: ${this.detail}`}`;
|
|
38
44
|
default: return `The blob store is misconfigured${this.detail === void 0 ? "" : `: ${this.detail}`}`;
|
|
39
45
|
}
|
|
40
46
|
}
|
|
@@ -75,10 +81,17 @@ var BlobStore = class BlobStore extends Context.Service()("@effected/github-acti
|
|
|
75
81
|
* An S3-compatible backend, signed with SigV4.
|
|
76
82
|
*
|
|
77
83
|
* @remarks
|
|
78
|
-
* No `@aws-sdk/*` dependency: signing is
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
84
|
+
* No `@aws-sdk/*` dependency: signing is `@effected/crypto`'s `SigV4`, a
|
|
85
|
+
* specified algorithm over strings and HMACs. The SDK's weight is in
|
|
86
|
+
* credential management, retries and a service catalogue none of which this
|
|
87
|
+
* needs.
|
|
88
|
+
*
|
|
89
|
+
* Requires core `Crypto` for the SHA-256 digests signing takes, resolved
|
|
90
|
+
* once when the layer is built; `NodeServices.layer` supplies it. A request
|
|
91
|
+
* that cannot be signed fails as {@link BlobStoreError} `misconfigured`. A
|
|
92
|
+
* key with a `.` or `..` path segment fails as `invalidKey` before anything
|
|
93
|
+
* is signed or sent: every URL parser collapses such a segment, so the store
|
|
94
|
+
* would receive another path than the one signed.
|
|
82
95
|
*
|
|
83
96
|
* A parameterized layer factory mints a fresh layer per call and layers
|
|
84
97
|
* memoize by reference — bind it to a `const` rather than calling it at each
|
|
@@ -119,43 +132,60 @@ var BlobStore = class BlobStore extends Context.Service()("@effected/github-acti
|
|
|
119
132
|
};
|
|
120
133
|
const dies = unstubbed("BlobStore.makeTest");
|
|
121
134
|
const makeS3 = (config) => Effect.gen(function* () {
|
|
122
|
-
const http = yield* HttpClient.HttpClient;
|
|
135
|
+
const http = HttpClient.transform(yield* HttpClient.HttpClient, (effect) => Effect.provideService(effect, HttpClient.TracerPropagationEnabled, false));
|
|
136
|
+
const crypto = yield* Crypto.Crypto;
|
|
123
137
|
let endpoint = config.endpoint ?? `https://s3.${config.region}.amazonaws.com`;
|
|
124
138
|
while (endpoint.endsWith("/")) endpoint = endpoint.slice(0, -1);
|
|
125
139
|
const host = new URL(endpoint).host;
|
|
126
|
-
|
|
127
|
-
|
|
140
|
+
yield* Secret.mask(config.secretAccessKey);
|
|
141
|
+
if (config.sessionToken !== void 0) yield* Secret.mask(config.sessionToken);
|
|
142
|
+
const credentials = {
|
|
143
|
+
accessKeyId: config.accessKeyId,
|
|
144
|
+
secretAccessKey: config.secretAccessKey,
|
|
145
|
+
...config.sessionToken === void 0 ? {} : { sessionToken: config.sessionToken },
|
|
146
|
+
region: config.region,
|
|
147
|
+
service: "s3"
|
|
148
|
+
};
|
|
128
149
|
const objectPath = (key) => [
|
|
129
150
|
config.bucket,
|
|
130
151
|
...config.prefix === void 0 ? [] : [config.prefix],
|
|
131
152
|
key
|
|
132
153
|
].join("/").replaceAll(/\/{2,}/g, "/");
|
|
133
|
-
const
|
|
154
|
+
const unsignable = (key, cause) => new BlobStoreError({
|
|
155
|
+
reason: "misconfigured",
|
|
156
|
+
key,
|
|
157
|
+
detail: "the request could not be signed",
|
|
158
|
+
cause
|
|
159
|
+
});
|
|
160
|
+
const request = (method, key, body) => Effect.gen(function* () {
|
|
134
161
|
const path = objectPath(key);
|
|
135
|
-
const
|
|
162
|
+
const now = yield* DateTime.now;
|
|
163
|
+
const signed = yield* SigV4.sign({
|
|
136
164
|
method,
|
|
137
165
|
path,
|
|
138
166
|
host,
|
|
139
|
-
headers: {},
|
|
140
167
|
body,
|
|
141
|
-
now
|
|
142
|
-
}, {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
168
|
+
now
|
|
169
|
+
}, credentials).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.catchTags({
|
|
170
|
+
SigV4PathError: (cause) => Effect.fail(new BlobStoreError({
|
|
171
|
+
reason: "invalidKey",
|
|
172
|
+
key,
|
|
173
|
+
detail: `the path has a "${cause.segment}" segment, which a URL collapses, so it cannot be sent as signed`,
|
|
174
|
+
cause
|
|
175
|
+
})),
|
|
176
|
+
CryptoError: (cause) => Effect.fail(unsignable(key, cause)),
|
|
177
|
+
PlatformError: (cause) => Effect.fail(unsignable(key, cause))
|
|
178
|
+
}));
|
|
149
179
|
return {
|
|
150
|
-
url: `${endpoint}
|
|
151
|
-
headers
|
|
180
|
+
url: `${endpoint}${signed.path}${signed.query === "" ? "" : `?${signed.query}`}`,
|
|
181
|
+
headers: signed.headers
|
|
152
182
|
};
|
|
153
|
-
};
|
|
154
|
-
const send = (method, key, body) => Effect.
|
|
155
|
-
const { url, headers } = request(method, key, body);
|
|
183
|
+
});
|
|
184
|
+
const send = (method, key, body) => Effect.gen(function* () {
|
|
185
|
+
const { url, headers } = yield* request(method, key, body);
|
|
156
186
|
const base = HttpClientRequest.make(method)(url, { headers });
|
|
157
187
|
const built = body.length === 0 ? base : HttpClientRequest.bodyUint8Array(base, body);
|
|
158
|
-
return http.execute(built).pipe(Effect.mapError((cause) => new BlobStoreError({
|
|
188
|
+
return yield* http.execute(built).pipe(Effect.mapError((cause) => new BlobStoreError({
|
|
159
189
|
reason: "unreachable",
|
|
160
190
|
key,
|
|
161
191
|
cause
|
|
@@ -193,5 +223,4 @@ const makeS3 = (config) => Effect.gen(function* () {
|
|
|
193
223
|
};
|
|
194
224
|
});
|
|
195
225
|
|
|
196
|
-
//#endregion
|
|
197
226
|
export { BlobStore, BlobStoreError };
|
package/BlobTransfer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/BlobTransfer.ts
|
|
4
4
|
/**
|
|
5
5
|
* Raised when bytes could not be moved to or from a signed blob url.
|
|
6
6
|
*
|
|
@@ -17,5 +17,4 @@ var BlobTransferError = class extends Schema.TaggedError()("BlobTransferError",
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
//#endregion
|
|
21
20
|
export { BlobTransferError };
|
package/CacheKey.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Effect, FileSystem, Option, Path, Schema } from "effect";
|
|
|
3
3
|
import { GlobSet } from "@effected/glob";
|
|
4
4
|
import { descend } from "@effected/walker";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/CacheKey.ts
|
|
7
7
|
/**
|
|
8
8
|
* Raised when a file or directory that was going to be hashed could not be
|
|
9
9
|
* read.
|
|
@@ -441,5 +441,4 @@ var CacheKey = class CacheKey extends Schema.Class("CacheKey")(Schema.Struct({
|
|
|
441
441
|
});
|
|
442
442
|
};
|
|
443
443
|
|
|
444
|
-
//#endregion
|
|
445
444
|
export { CacheKey, CacheKeyBadPatternError, CacheKeyReadError };
|
package/CheckDocument.js
CHANGED
|
@@ -3,7 +3,7 @@ import { CheckState } from "./CheckState.js";
|
|
|
3
3
|
import { ManagedDocument } from "./ManagedDocument.js";
|
|
4
4
|
import { Clock, Context, Duration, Effect, Latch, Layer, Ref, Schema, Semaphore } from "effect";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/CheckDocument.ts
|
|
7
7
|
/**
|
|
8
8
|
* What a run knows about one of its checks: the authoritative state, and the
|
|
9
9
|
* presentation facts a renderer projects into the document.
|
|
@@ -311,5 +311,4 @@ var CheckDocument = class CheckDocument extends Context.Service()("@effected/git
|
|
|
311
311
|
};
|
|
312
312
|
const dies = unstubbed("CheckDocument.makeTest");
|
|
313
313
|
|
|
314
|
-
//#endregion
|
|
315
314
|
export { CheckDocument, CheckDocumentError, CheckDocumentStamp, CheckReport };
|
package/CheckState.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// src/CheckState.ts
|
|
4
4
|
/**
|
|
5
5
|
* The kit's check-state vocabulary.
|
|
6
6
|
*
|
|
@@ -71,5 +71,4 @@ const projectCheckState = (state) => {
|
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
//#endregion
|
|
75
74
|
export { CheckState, projectCheckState };
|
package/ChildEnv.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/ChildEnv.ts
|
|
2
2
|
/**
|
|
3
3
|
* Child-process environment construction: prepending directories to `PATH`
|
|
4
4
|
* without falling into three cross-platform traps.
|
|
@@ -127,5 +127,4 @@ var ChildEnv = class ChildEnv {
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
|
|
130
|
-
//#endregion
|
|
131
130
|
export { ChildEnv };
|
package/DetachedProcess.js
CHANGED
|
@@ -6,7 +6,7 @@ import { ChildProcessSpawner } from "effect/process";
|
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
7
|
import { closeSync, openSync } from "node:fs";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
// src/DetachedProcess.ts
|
|
10
10
|
/**
|
|
11
11
|
* Raised when the log file for a detached child's output cannot be opened.
|
|
12
12
|
*
|
|
@@ -309,5 +309,4 @@ var DetachedProcess = class DetachedProcess {
|
|
|
309
309
|
});
|
|
310
310
|
};
|
|
311
311
|
|
|
312
|
-
//#endregion
|
|
313
312
|
export { DetachedLogUnavailableError, DetachedNotReadyError, DetachedProcess, DetachedSignalFailedError, DetachedSpawnFailedError, InvalidPidError, ProcessId };
|
package/DryRun.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActionInput } from "./ActionInput.js";
|
|
2
2
|
import { Config, Context, Effect, Layer } from "effect";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/DryRun.ts
|
|
5
5
|
/** The input a workflow author sets to rehearse a run. */
|
|
6
6
|
const DEFAULT_INPUT = "dry-run";
|
|
7
7
|
const make = (enabled) => ({
|
|
@@ -69,5 +69,4 @@ var DryRun = class DryRun extends Context.Service()("@effected/github-actions/Dr
|
|
|
69
69
|
static layerTest = (overrides = {}) => Layer.succeed(DryRun, DryRun.makeTest(overrides));
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
//#endregion
|
|
73
72
|
export { DryRun };
|
package/GitHubMarkdown.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Result, Schema, SchemaAST } from "effect";
|
|
2
2
|
import { Code, Html, InlineCode, Link, List, ListItem, Markdown, Paragraph, Root, Table, TableCell, TableRow } from "@effected/markdown";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/GitHubMarkdown.ts
|
|
5
5
|
/**
|
|
6
6
|
* A block node whose value passes through the serializer verbatim, which is
|
|
7
7
|
* exactly how a pre-rendered markdown fragment must travel: GFM structure
|
|
@@ -234,5 +234,4 @@ var GitHubMarkdown = class GitHubMarkdown {
|
|
|
234
234
|
}
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
-
//#endregion
|
|
238
237
|
export { GitHubMarkdown };
|
package/GitHubToken.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Secret } from "./Secret.js";
|
|
|
3
3
|
import { DateTime, Duration, Effect, Exit, Layer, Option, Result, Schema } from "effect";
|
|
4
4
|
import { GitHubApp, GitHubClient, InstallationToken, TokenPermissions } from "@effected/github";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// src/GitHubToken.ts
|
|
7
7
|
/**
|
|
8
8
|
* Raised when the token an earlier phase persisted cannot be used.
|
|
9
9
|
*
|
|
@@ -220,5 +220,4 @@ var GitHubToken = class GitHubToken {
|
|
|
220
220
|
});
|
|
221
221
|
};
|
|
222
222
|
|
|
223
|
-
//#endregion
|
|
224
223
|
export { GitHubToken, GitHubTokenError };
|
package/ManagedDocument.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Effect, Option, Result, Schema } from "effect";
|
|
2
2
|
import { CommentStyle, SectionDialect, SectionDocument, SectionId } from "@effected/templates";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/ManagedDocument.ts
|
|
5
5
|
/**
|
|
6
6
|
* The grammar shared by a document's `namespace`, its `key` and every region
|
|
7
7
|
* key.
|
|
@@ -316,5 +316,4 @@ var ManagedDocument = class ManagedDocument extends Schema.Class("ManagedDocumen
|
|
|
316
316
|
}
|
|
317
317
|
};
|
|
318
318
|
|
|
319
|
-
//#endregion
|
|
320
319
|
export { ManagedDocument, ManagedDocumentError };
|