@effected/github-actions 0.1.0 → 0.2.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/ActionLogger.js +7 -3
- package/ActionsIdentityToken.js +61 -0
- package/ActionsProvenance.js +103 -0
- package/CheckDocument.js +193 -0
- package/CheckState.js +75 -0
- package/GitHubMarkdown.js +197 -0
- package/ManagedDocument.js +281 -0
- package/README.md +241 -0
- package/Secret.js +13 -0
- package/index.d.ts +1009 -167
- package/index.js +8 -2
- package/package.json +6 -3
package/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { NodeServices } from "@effect/platform-node";
|
|
|
2
2
|
import { Cause, Config, ConfigProvider, Context, Duration, Effect, FileSystem, Layer, Logger, Option, Path, Redacted, Result, Schema } from "effect";
|
|
3
3
|
import { HttpClient } from "effect/unstable/http";
|
|
4
4
|
import { ChildProcessSpawner } from "effect/unstable/process";
|
|
5
|
+
import { IdentityToken, SlsaProvenance } from "@effected/sbom";
|
|
5
6
|
import { BotIdentity, GitHubApp, GitHubClient, InstallationToken, PermissionLevel, RetryPolicy } from "@effected/github";
|
|
6
7
|
//#region src/ActionEnvironment.d.ts
|
|
7
8
|
declare const ActionEnvironmentError_base: Schema.Class<ActionEnvironmentError, Schema.TaggedStruct<"ActionEnvironmentError", {
|
|
@@ -237,6 +238,24 @@ declare class WorkflowCommand {
|
|
|
237
238
|
}
|
|
238
239
|
//#endregion
|
|
239
240
|
//#region src/ActionLogger.d.ts
|
|
241
|
+
/**
|
|
242
|
+
* Options for {@link ActionLoggerShape.withBuffer}.
|
|
243
|
+
*
|
|
244
|
+
* @public
|
|
245
|
+
*/
|
|
246
|
+
interface WithBufferOptions {
|
|
247
|
+
/**
|
|
248
|
+
* What happens to the captured transcript when the step **succeeds**.
|
|
249
|
+
*
|
|
250
|
+
* @remarks
|
|
251
|
+
* `"flush"` — the default — replays it, so a clean run still prints what it
|
|
252
|
+
* did. `"discard"` drops it, which is what keeps a green release log to one
|
|
253
|
+
* line per step: the transcript exists only as the failure report. A failure,
|
|
254
|
+
* a defect or an interruption flushes under either setting — the choice is
|
|
255
|
+
* only about what a success is worth in the log.
|
|
256
|
+
*/
|
|
257
|
+
readonly onSuccess?: "flush" | "discard";
|
|
258
|
+
}
|
|
240
259
|
/**
|
|
241
260
|
* The {@link ActionLogger} service shape.
|
|
242
261
|
*
|
|
@@ -252,13 +271,18 @@ interface ActionLoggerShape {
|
|
|
252
271
|
* Warnings and errors are **not** buffered — they go out as they happen, so a
|
|
253
272
|
* long step still reports trouble while it is running. Everything at `Info`
|
|
254
273
|
* and below is held and flushed on every exit path, including a defect or an
|
|
255
|
-
* interruption, so a clean run still prints its transcript.
|
|
274
|
+
* interruption, so a clean run still prints its transcript. A step that
|
|
275
|
+
* should be **quiet** when it succeeds passes
|
|
276
|
+
* `{ onSuccess: "discard" }` ({@link WithBufferOptions}); failure still
|
|
277
|
+
* spills the transcript either way.
|
|
256
278
|
*
|
|
257
279
|
* Buffering is skipped entirely when the runner has step debugging enabled or
|
|
258
280
|
* the ambient minimum log level is already `Debug` or lower — someone asking
|
|
259
|
-
* for verbose output wants it live
|
|
281
|
+
* for verbose output wants it live, and that overrides
|
|
282
|
+
* `onSuccess: "discard"` too: asking for debug output means wanting to see
|
|
283
|
+
* what a green step did.
|
|
260
284
|
*/
|
|
261
|
-
readonly withBuffer: <A, E, R>(label: string, effect: Effect.Effect<A, E, R
|
|
285
|
+
readonly withBuffer: <A, E, R>(label: string, effect: Effect.Effect<A, E, R>, options?: WithBufferOptions) => Effect.Effect<A, E, R>;
|
|
262
286
|
/**
|
|
263
287
|
* Emit a `::notice::` annotation.
|
|
264
288
|
*
|
|
@@ -1176,6 +1200,288 @@ declare class ActionInput {
|
|
|
1176
1200
|
static readonly layerDefault: Layer.Layer<never>;
|
|
1177
1201
|
}
|
|
1178
1202
|
//#endregion
|
|
1203
|
+
//#region src/OidcTokenIssuer.d.ts
|
|
1204
|
+
declare const OidcTokenError_base: Schema.Class<OidcTokenError, Schema.TaggedStruct<"OidcTokenError", {
|
|
1205
|
+
/**
|
|
1206
|
+
* `unavailable` — the runner did not publish the token-service variables,
|
|
1207
|
+
* which almost always means the workflow is missing `permissions: id-token:
|
|
1208
|
+
* write`. `requestFailed` — the token service could not be reached or refused
|
|
1209
|
+
* the request. `malformedResponse` — it answered with something that is not a
|
|
1210
|
+
* token envelope. `malformedToken` — the token is not a decodable JWT.
|
|
1211
|
+
* `missingClaims` — it decoded, but without the claims a provenance statement
|
|
1212
|
+
* needs.
|
|
1213
|
+
*/
|
|
1214
|
+
readonly reason: Schema.Literals<readonly ["unavailable", "requestFailed", "malformedResponse", "malformedToken", "missingClaims"]>;
|
|
1215
|
+
/** What was wrong, in one line. */
|
|
1216
|
+
readonly detail: Schema.optionalKey<Schema.String>;
|
|
1217
|
+
/** The HTTP status, when the token service answered. */
|
|
1218
|
+
readonly status: Schema.optionalKey<Schema.Number>;
|
|
1219
|
+
/** The underlying failure, preserved structurally. */
|
|
1220
|
+
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
1221
|
+
}>, import("effect/Cause").YieldableError>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Raised when an OIDC token cannot be issued or read.
|
|
1224
|
+
*
|
|
1225
|
+
* @public
|
|
1226
|
+
*/
|
|
1227
|
+
declare class OidcTokenError extends OidcTokenError_base {
|
|
1228
|
+
get message(): string;
|
|
1229
|
+
}
|
|
1230
|
+
declare const OidcClaims_base: Schema.Class<OidcClaims, Schema.Struct<{
|
|
1231
|
+
/** The issuer, e.g. `https://token.actions.githubusercontent.com`. */
|
|
1232
|
+
readonly iss: Schema.String;
|
|
1233
|
+
/** The full ref the workflow ran on. */
|
|
1234
|
+
readonly ref: Schema.String;
|
|
1235
|
+
/** The commit. */
|
|
1236
|
+
readonly sha: Schema.String;
|
|
1237
|
+
/** `owner/repo`. */
|
|
1238
|
+
readonly repository: Schema.String;
|
|
1239
|
+
/** The event that triggered the run. */
|
|
1240
|
+
readonly event_name: Schema.String;
|
|
1241
|
+
/** The reusable-workflow ref, which is what a verifier pins against. */
|
|
1242
|
+
readonly job_workflow_ref: Schema.String;
|
|
1243
|
+
/** The calling workflow's ref. */
|
|
1244
|
+
readonly workflow_ref: Schema.String;
|
|
1245
|
+
/** The numeric repository id, as a string. */
|
|
1246
|
+
readonly repository_id: Schema.String;
|
|
1247
|
+
/** The numeric owner id, as a string. */
|
|
1248
|
+
readonly repository_owner_id: Schema.String;
|
|
1249
|
+
/** `github-hosted` or `self-hosted`. */
|
|
1250
|
+
readonly runner_environment: Schema.String;
|
|
1251
|
+
/** The run id, as a string. */
|
|
1252
|
+
readonly run_id: Schema.String;
|
|
1253
|
+
/** The run attempt, as a string. */
|
|
1254
|
+
readonly run_attempt: Schema.String;
|
|
1255
|
+
}>, {}>;
|
|
1256
|
+
/**
|
|
1257
|
+
* The claims a GitHub Actions OIDC token carries about the workflow that ran.
|
|
1258
|
+
*
|
|
1259
|
+
* @remarks
|
|
1260
|
+
* The field names are GitHub's own JWT claim names, kept verbatim rather than
|
|
1261
|
+
* translated to the kit's casing. They are an **external vocabulary** — the
|
|
1262
|
+
* same strings that appear in a SLSA provenance predicate and in every
|
|
1263
|
+
* published example of an Actions OIDC policy — and renaming them would put a
|
|
1264
|
+
* translation layer between a consumer and the specification they are reading.
|
|
1265
|
+
*
|
|
1266
|
+
* @public
|
|
1267
|
+
*/
|
|
1268
|
+
declare class OidcClaims extends OidcClaims_base {}
|
|
1269
|
+
/**
|
|
1270
|
+
* The {@link OidcTokenIssuer} service shape.
|
|
1271
|
+
*
|
|
1272
|
+
* @public
|
|
1273
|
+
*/
|
|
1274
|
+
interface OidcTokenIssuerShape {
|
|
1275
|
+
/**
|
|
1276
|
+
* Request an ID token, optionally bound to an audience.
|
|
1277
|
+
*
|
|
1278
|
+
* @remarks
|
|
1279
|
+
* Omitting the audience sends no `audience` parameter at all, matching
|
|
1280
|
+
* `@actions/core.getIDToken` — the runner's default audience is not the empty
|
|
1281
|
+
* string.
|
|
1282
|
+
*/
|
|
1283
|
+
readonly token: (audience?: string) => Effect.Effect<Redacted.Redacted<string>, OidcTokenError>;
|
|
1284
|
+
/**
|
|
1285
|
+
* The token's claims, decoded.
|
|
1286
|
+
*
|
|
1287
|
+
* @remarks
|
|
1288
|
+
* **The signature is deliberately not verified**, for three reasons that are
|
|
1289
|
+
* recorded so nobody "fixes" it:
|
|
1290
|
+
*
|
|
1291
|
+
* 1. The token comes from the runner's own token-service endpoint over TLS.
|
|
1292
|
+
* The transport is the trust boundary, and the process asking for the
|
|
1293
|
+
* token is the process that received it.
|
|
1294
|
+
* 2. The claims populate a provenance predicate, not a trust decision.
|
|
1295
|
+
* Nothing branches on them for authorization; they are recorded as
|
|
1296
|
+
* attested facts about the workflow that ran.
|
|
1297
|
+
* 3. Verifying would need a JWKS fetch, which turns a decode into a network
|
|
1298
|
+
* call — untestable without a fixture server, and dependent on GitHub's
|
|
1299
|
+
* key endpoint being reachable at attestation time.
|
|
1300
|
+
*
|
|
1301
|
+
* A consumer that needs a *verified* token needs a different operation with a
|
|
1302
|
+
* different name and a different error channel, not an option on this one.
|
|
1303
|
+
*
|
|
1304
|
+
* Claims are on the surface rather than left to the call site because that is
|
|
1305
|
+
* what makes the provenance path reachable in a test: a double built with
|
|
1306
|
+
* {@link OidcTokenIssuer.layerFor} answers with real, decodable claims, where
|
|
1307
|
+
* the synthetic non-JWT its predecessor returned made every consumer's
|
|
1308
|
+
* `decodeJwtClaims` yield nothing and silently skipped the path under test.
|
|
1309
|
+
*/
|
|
1310
|
+
readonly claims: (audience?: string) => Effect.Effect<OidcClaims, OidcTokenError>;
|
|
1311
|
+
}
|
|
1312
|
+
declare const OidcTokenIssuer_base: Context.ServiceClass<OidcTokenIssuer, "@effected/github-actions/OidcTokenIssuer", OidcTokenIssuerShape>;
|
|
1313
|
+
/**
|
|
1314
|
+
* The runner's OIDC token service.
|
|
1315
|
+
*
|
|
1316
|
+
* @remarks
|
|
1317
|
+
* Lives here rather than with attestation because it reads
|
|
1318
|
+
* `ACTIONS_ID_TOKEN_REQUEST_TOKEN` and `ACTIONS_ID_TOKEN_REQUEST_URL`, which
|
|
1319
|
+
* exist only when a workflow declares `permissions: id-token: write` — that is
|
|
1320
|
+
* a fact about the runner, not about signing.
|
|
1321
|
+
*
|
|
1322
|
+
* @example
|
|
1323
|
+
* ```ts
|
|
1324
|
+
* import { OidcTokenIssuer } from "@effected/github-actions";
|
|
1325
|
+
* import { Effect } from "effect";
|
|
1326
|
+
*
|
|
1327
|
+
* const program = Effect.gen(function* () {
|
|
1328
|
+
* const issuer = yield* OidcTokenIssuer;
|
|
1329
|
+
* const claims = yield* issuer.claims("sigstore");
|
|
1330
|
+
* return claims.job_workflow_ref;
|
|
1331
|
+
* });
|
|
1332
|
+
* ```
|
|
1333
|
+
*
|
|
1334
|
+
* @public
|
|
1335
|
+
*/
|
|
1336
|
+
declare class OidcTokenIssuer extends OidcTokenIssuer_base {
|
|
1337
|
+
static readonly layer: Layer.Layer<OidcTokenIssuer, never, ActionEnvironment | HttpClient.HttpClient>;
|
|
1338
|
+
/**
|
|
1339
|
+
* An **unsigned** JWT carrying these claims.
|
|
1340
|
+
*
|
|
1341
|
+
* @remarks
|
|
1342
|
+
* For building test doubles, and nothing else: the signature segment is a
|
|
1343
|
+
* placeholder, so this token would fail any verifier. It exists because the
|
|
1344
|
+
* alternative — a double returning a synthetic non-JWT — is what made the
|
|
1345
|
+
* provenance path structurally unreachable in the source package, drawing
|
|
1346
|
+
* four separate apologetic comments from one consumer.
|
|
1347
|
+
*/
|
|
1348
|
+
static readonly unsignedTokenFor: (claims: OidcClaims) => Redacted.Redacted<string>;
|
|
1349
|
+
/** A test double. Unstubbed members die rather than answering with a non-token. */
|
|
1350
|
+
static readonly makeTest: (overrides?: Partial<OidcTokenIssuerShape>) => OidcTokenIssuerShape;
|
|
1351
|
+
/** {@link OidcTokenIssuer.makeTest} behind `Layer.succeed`. */
|
|
1352
|
+
static readonly layerTest: (overrides?: Partial<OidcTokenIssuerShape>) => Layer.Layer<OidcTokenIssuer>;
|
|
1353
|
+
/**
|
|
1354
|
+
* A double that answers with these claims, consistently on both members.
|
|
1355
|
+
*
|
|
1356
|
+
* @remarks
|
|
1357
|
+
* `token()` returns a real decodable JWT built from the same claims
|
|
1358
|
+
* `claims()` returns, so a consumer that decodes the token itself and a
|
|
1359
|
+
* consumer that asks the service both see the same thing. A double whose two
|
|
1360
|
+
* members can disagree is how a test proves a path works while production
|
|
1361
|
+
* takes the other one.
|
|
1362
|
+
*/
|
|
1363
|
+
static readonly layerFor: (claims: OidcClaims) => Layer.Layer<OidcTokenIssuer>;
|
|
1364
|
+
}
|
|
1365
|
+
//#endregion
|
|
1366
|
+
//#region src/ActionsIdentityToken.d.ts
|
|
1367
|
+
/**
|
|
1368
|
+
* The Actions side of `@effected/sbom`'s inverted OIDC contract.
|
|
1369
|
+
*
|
|
1370
|
+
* @remarks
|
|
1371
|
+
* `@effected/sbom` declares `IdentityToken` — one method, one audience,
|
|
1372
|
+
* one redacted token — precisely so that signing does not drag the Actions
|
|
1373
|
+
* runtime into every consumer that only wants to emit an SBOM. This is the
|
|
1374
|
+
* layer that closes the inversion from the other side: it serves that contract
|
|
1375
|
+
* from the runner's own OIDC token service ({@link OidcTokenIssuer}), the same
|
|
1376
|
+
* arrangement as `@effected/workspaces` implementing `@effected/commands`'
|
|
1377
|
+
* `LocalExec`.
|
|
1378
|
+
*
|
|
1379
|
+
* The audience is forwarded verbatim. `SigstoreSigner` asks its identity
|
|
1380
|
+
* contract for the `sigstore` audience itself (`SIGSTORE_OIDC_AUDIENCE` is the
|
|
1381
|
+
* signing protocol's requirement, owned there), so nothing here — and nothing
|
|
1382
|
+
* in a consumer — needs to spell it.
|
|
1383
|
+
*
|
|
1384
|
+
* An `OidcTokenError` is rewrapped as `IdentityTokenError` with the
|
|
1385
|
+
* original preserved structurally in `cause`, so a refused exchange still says
|
|
1386
|
+
* which audience it was minting for **and** why the runner declined —
|
|
1387
|
+
* `reason: "unavailable"` almost always means the workflow is missing
|
|
1388
|
+
* `permissions: id-token: write`.
|
|
1389
|
+
*
|
|
1390
|
+
* @example
|
|
1391
|
+
* ```ts
|
|
1392
|
+
* import { ActionsIdentityToken, OidcTokenIssuer } from "@effected/github-actions";
|
|
1393
|
+
* import { SigstoreSigner } from "@effected/sbom";
|
|
1394
|
+
* import { Layer } from "effect";
|
|
1395
|
+
*
|
|
1396
|
+
* const signing = SigstoreSigner.layer.pipe(
|
|
1397
|
+
* Layer.provide(ActionsIdentityToken.layer),
|
|
1398
|
+
* Layer.provide(OidcTokenIssuer.layer),
|
|
1399
|
+
* );
|
|
1400
|
+
* ```
|
|
1401
|
+
*
|
|
1402
|
+
* @public
|
|
1403
|
+
*/
|
|
1404
|
+
declare class ActionsIdentityToken {
|
|
1405
|
+
private constructor();
|
|
1406
|
+
/**
|
|
1407
|
+
* `IdentityToken` served by the runner's OIDC token service.
|
|
1408
|
+
*
|
|
1409
|
+
* @remarks
|
|
1410
|
+
* Requires {@link OidcTokenIssuer} rather than composing
|
|
1411
|
+
* `OidcTokenIssuer.layer` in, so an action that already wired the issuer —
|
|
1412
|
+
* every action using `ActionRuntime.layer` has its requirements at hand —
|
|
1413
|
+
* does not construct a second one.
|
|
1414
|
+
*/
|
|
1415
|
+
static readonly layer: Layer.Layer<IdentityToken, never, OidcTokenIssuer>;
|
|
1416
|
+
}
|
|
1417
|
+
//#endregion
|
|
1418
|
+
//#region src/ActionsProvenance.d.ts
|
|
1419
|
+
/**
|
|
1420
|
+
* The Actions side of `@effected/sbom`'s SLSA provenance constructor.
|
|
1421
|
+
*
|
|
1422
|
+
* @remarks
|
|
1423
|
+
* `SlsaProvenance.forGitHubWorkflow` is total and does the real work, but it
|
|
1424
|
+
* takes a camelCase input record — and the only input anyone inside a workflow
|
|
1425
|
+
* actually holds is the runner's own OIDC claims, spelled in GitHub's
|
|
1426
|
+
* snake_case claim names. The rename between the two is eleven all-string
|
|
1427
|
+
* fields, so transposing `repository_id` and `repository_owner_id` compiles,
|
|
1428
|
+
* passes every type check, and produces a validly signed attestation asserting
|
|
1429
|
+
* the **wrong** provenance. This module owns that rename once, on the same
|
|
1430
|
+
* `github-actions` ↔ `sbom` seam as {@link ActionsIdentityToken}: `sbom` must
|
|
1431
|
+
* not depend on the Actions runtime, so the adapter lives here, beside the
|
|
1432
|
+
* services it reads.
|
|
1433
|
+
*
|
|
1434
|
+
* The construct ends at the predicate. Assembling the in-toto statement,
|
|
1435
|
+
* signing it and uploading the bundle stay with the consumer — that pipeline
|
|
1436
|
+
* is deliberately consumer glue (see `@effected/sbom`'s `SigstoreSigner` and
|
|
1437
|
+
* `@effected/github`'s `Attestation.upload`).
|
|
1438
|
+
*
|
|
1439
|
+
* @example
|
|
1440
|
+
* ```ts
|
|
1441
|
+
* import { ActionsProvenance } from "@effected/github-actions";
|
|
1442
|
+
* import { Effect } from "effect";
|
|
1443
|
+
*
|
|
1444
|
+
* const program = Effect.gen(function* () {
|
|
1445
|
+
* const provenance = yield* ActionsProvenance.capture();
|
|
1446
|
+
* return provenance.runDetails.builder.id;
|
|
1447
|
+
* });
|
|
1448
|
+
* ```
|
|
1449
|
+
*
|
|
1450
|
+
* @public
|
|
1451
|
+
*/
|
|
1452
|
+
declare class ActionsProvenance {
|
|
1453
|
+
private constructor();
|
|
1454
|
+
/**
|
|
1455
|
+
* The current run's SLSA provenance, built from the runner's OIDC claims.
|
|
1456
|
+
*
|
|
1457
|
+
* @remarks
|
|
1458
|
+
* Every field `GitHubWorkflowProvenance` declares is populated from
|
|
1459
|
+
* {@link OidcClaims}, except `serverUrl`, which is read from
|
|
1460
|
+
* `GITHUB_SERVER_URL` through {@link ActionEnvironment}'s `getOptional`
|
|
1461
|
+
* with `https://github.com` as the default — **not** through the
|
|
1462
|
+
* `GitHubContext` projection. The projection fails typed when a `GITHUB_*`
|
|
1463
|
+
* variable is missing, and a missing server URL is not a failure: it has a
|
|
1464
|
+
* correct default. GHES consumers set the variable, github.com consumers
|
|
1465
|
+
* never should have to, and neither should think about it. (Upstream
|
|
1466
|
+
* `@actions/attest` reads the same variable with no default and writes the
|
|
1467
|
+
* literal string `undefined` into every URL it builds — the hazard
|
|
1468
|
+
* `GitHubWorkflowProvenance.serverUrl` being a required field exists to
|
|
1469
|
+
* prevent.)
|
|
1470
|
+
*
|
|
1471
|
+
* The audience is forwarded to {@link OidcTokenIssuerShape.claims}
|
|
1472
|
+
* verbatim; the claims a provenance reads do not depend on it, so omitting
|
|
1473
|
+
* it is fine and spends no extra token mint.
|
|
1474
|
+
*
|
|
1475
|
+
* An {@link OidcTokenError} passes through **untouched** — not caught, not
|
|
1476
|
+
* defaulted, not wrapped. Whether attestation is mandatory or best-effort
|
|
1477
|
+
* is the consumer's policy: an action that must not publish unattested
|
|
1478
|
+
* lets the error propagate, and one that publishes anyway catches it at
|
|
1479
|
+
* its own boundary. `reason: "unavailable"` almost always means the
|
|
1480
|
+
* workflow is missing `permissions: id-token: write`.
|
|
1481
|
+
*/
|
|
1482
|
+
static readonly capture: (audience?: string) => Effect.Effect<SlsaProvenance, OidcTokenError, OidcTokenIssuer | ActionEnvironment>;
|
|
1483
|
+
}
|
|
1484
|
+
//#endregion
|
|
1179
1485
|
//#region src/Artifact.d.ts
|
|
1180
1486
|
declare const ArtifactError_base: Schema.Class<ArtifactError, Schema.TaggedStruct<"ArtifactError", {
|
|
1181
1487
|
/**
|
|
@@ -1625,55 +1931,338 @@ declare class GitHubCacheBlobStore {
|
|
|
1625
1931
|
static readonly layerWith: (transfer: DataBlobTransfer) => Layer.Layer<BlobStore, never, HttpClient.HttpClient | ActionEnvironment>;
|
|
1626
1932
|
}
|
|
1627
1933
|
//#endregion
|
|
1628
|
-
//#region src/
|
|
1629
|
-
declare const
|
|
1630
|
-
/**
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1934
|
+
//#region src/CheckDocument.d.ts
|
|
1935
|
+
declare const CheckReport_base: Schema.Class<CheckReport, Schema.Struct<{
|
|
1936
|
+
/** Where the check is now. The last reported state is the authoritative one. */
|
|
1937
|
+
readonly state: Schema.Literals<readonly ["running", "pass", "fail", "warn", "user_interaction_required", "skipped", "timeout"]>;
|
|
1938
|
+
/** Display name, when it differs from the registry key. */
|
|
1939
|
+
readonly title: Schema.optionalKey<Schema.String>;
|
|
1940
|
+
/** A one-line verdict, e.g. `in progress...` or `3 packages ready`. */
|
|
1941
|
+
readonly outcome: Schema.optionalKey<Schema.String>;
|
|
1942
|
+
/** A pre-rendered markdown block of per-check detail. */
|
|
1943
|
+
readonly detail: Schema.optionalKey<Schema.String>;
|
|
1944
|
+
/** Where the check's name should link. */
|
|
1945
|
+
readonly url: Schema.optionalKey<Schema.String>;
|
|
1946
|
+
}>, {}>;
|
|
1947
|
+
/**
|
|
1948
|
+
* What a run knows about one of its checks: the authoritative state, and the
|
|
1949
|
+
* presentation facts a renderer projects into the document.
|
|
1950
|
+
*
|
|
1951
|
+
* @remarks
|
|
1952
|
+
* Only `state` is required. The rest exist because a status table needs them:
|
|
1953
|
+
* `title` when the display name differs from the registry key, `outcome` for
|
|
1954
|
+
* the one-line verdict cell, `url` for linking the check's name, and `detail`
|
|
1955
|
+
* for the per-check block a body region carries. A later report for the same
|
|
1956
|
+
* key **replaces** the whole entry — last write wins, per field and per check.
|
|
1957
|
+
*
|
|
1958
|
+
* @public
|
|
1959
|
+
*/
|
|
1960
|
+
declare class CheckReport extends CheckReport_base {}
|
|
1961
|
+
declare const CheckDocumentError_base: Schema.Class<CheckDocumentError, Schema.TaggedStruct<"CheckDocumentError", {
|
|
1962
|
+
/** Which half failed: regenerating the document, or writing it. */
|
|
1963
|
+
readonly kind: Schema.Literals<readonly ["render", "sink"]>;
|
|
1964
|
+
/** The underlying failure. */
|
|
1644
1965
|
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
1645
1966
|
}>, import("effect/Cause").YieldableError>;
|
|
1646
1967
|
/**
|
|
1647
|
-
* Raised when
|
|
1968
|
+
* Raised when the check document cannot be regenerated or written.
|
|
1969
|
+
*
|
|
1970
|
+
* @remarks
|
|
1971
|
+
* `render` — projecting the registry onto the document failed, almost always
|
|
1972
|
+
* because a reported `detail` contains a line the region scanner would read
|
|
1973
|
+
* as a marker; the underlying `ManagedDocumentError` rides in `cause`.
|
|
1974
|
+
* `sink` — the consumer's write effect failed; its error rides in `cause`.
|
|
1975
|
+
* Callers of `flush` branch on `kind`; the background reconciler never fails
|
|
1976
|
+
* a fiber with this — it logs and retries on the next report.
|
|
1648
1977
|
*
|
|
1649
1978
|
* @public
|
|
1650
1979
|
*/
|
|
1651
|
-
declare class
|
|
1980
|
+
declare class CheckDocumentError extends CheckDocumentError_base {
|
|
1652
1981
|
get message(): string;
|
|
1653
1982
|
}
|
|
1654
1983
|
/**
|
|
1655
|
-
*
|
|
1984
|
+
* How a rendered document leaves the process: the narrow sink contract.
|
|
1656
1985
|
*
|
|
1657
1986
|
* @remarks
|
|
1658
|
-
*
|
|
1659
|
-
*
|
|
1660
|
-
*
|
|
1661
|
-
*
|
|
1662
|
-
*
|
|
1663
|
-
*
|
|
1664
|
-
* than the only one.
|
|
1987
|
+
* One rendered document in, one write effect out — nothing else. That is
|
|
1988
|
+
* what lets the sticky PR comment (`PullRequestComment.upsert`), the PR
|
|
1989
|
+
* description (`PATCH` on the pull request) and a test's recording `Ref` all
|
|
1990
|
+
* fit the same reconciler. The success value is ignored; a failure surfaces
|
|
1991
|
+
* as {@link CheckDocumentError} with `kind: "sink"`. Provide any services the
|
|
1992
|
+
* write needs when constructing the sink — the reconciler runs it as given.
|
|
1665
1993
|
*
|
|
1666
|
-
*
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
*
|
|
1671
|
-
* the spawner just produced, and exactly wrong for a pid that has been through a
|
|
1672
|
-
* text file. This schema is that missing check, and it decodes to core's type so
|
|
1673
|
-
* the two are interchangeable.
|
|
1994
|
+
* @public
|
|
1995
|
+
*/
|
|
1996
|
+
type CheckDocumentSink = (rendered: string) => Effect.Effect<unknown, unknown>;
|
|
1997
|
+
/**
|
|
1998
|
+
* Options for {@link CheckDocument.layer}.
|
|
1674
1999
|
*
|
|
1675
|
-
* @
|
|
1676
|
-
|
|
2000
|
+
* @public
|
|
2001
|
+
*/
|
|
2002
|
+
interface CheckDocumentOptions {
|
|
2003
|
+
/** The managed document's namespace, e.g. your action's name. */
|
|
2004
|
+
readonly namespace: string;
|
|
2005
|
+
/** Which document, within that namespace. */
|
|
2006
|
+
readonly key: string;
|
|
2007
|
+
/**
|
|
2008
|
+
* The document text to reconcile against initially — a PR body fetched
|
|
2009
|
+
* once at startup, so human content outside the managed regions survives.
|
|
2010
|
+
* Defaults to empty: a fresh document.
|
|
2011
|
+
*/
|
|
2012
|
+
readonly initial?: string | undefined;
|
|
2013
|
+
/**
|
|
2014
|
+
* The pure projection from registry state to region entries.
|
|
2015
|
+
*
|
|
2016
|
+
* @remarks
|
|
2017
|
+
* Called with the full snapshot on every reconcile pass; returns the
|
|
2018
|
+
* regions to replace, keyed however the consumer's document is laid out —
|
|
2019
|
+
* typically one region per check plus a shared status table. It must be a
|
|
2020
|
+
* pure function of the snapshot: rendering the same state twice must
|
|
2021
|
+
* produce the same entries, because byte-identical output is what
|
|
2022
|
+
* suppresses the write.
|
|
2023
|
+
*/
|
|
2024
|
+
readonly render: (checks: ReadonlyMap<string, CheckReport>) => ReadonlyArray<readonly [key: string, content: string]>;
|
|
2025
|
+
/** Where the rendered document goes. */
|
|
2026
|
+
readonly sink: CheckDocumentSink;
|
|
2027
|
+
/**
|
|
2028
|
+
* Debounce parameters: `quiet` is the trailing settle window, `maxWait`
|
|
2029
|
+
* the staleness bound under a steady stream of reports. Defaults: 500
|
|
2030
|
+
* milliseconds and 3 seconds.
|
|
2031
|
+
*/
|
|
2032
|
+
readonly debounce?: {
|
|
2033
|
+
readonly quiet?: Duration.Input | undefined;
|
|
2034
|
+
readonly maxWait?: Duration.Input | undefined;
|
|
2035
|
+
} | undefined;
|
|
2036
|
+
/**
|
|
2037
|
+
* How long one sink write may run before the pass fails with
|
|
2038
|
+
* `kind: "sink"`. Default: 30 seconds.
|
|
2039
|
+
*
|
|
2040
|
+
* @remarks
|
|
2041
|
+
* The reconciler serializes passes behind one permit, and the finalizer's
|
|
2042
|
+
* last flush waits on that same permit — so a sink that never resolves
|
|
2043
|
+
* would otherwise stall every later pass AND scope teardown. The bound
|
|
2044
|
+
* turns a hung write into the ordinary sink failure path: a background
|
|
2045
|
+
* pass logs and retries on the next report, `flush` surfaces the typed
|
|
2046
|
+
* error.
|
|
2047
|
+
*/
|
|
2048
|
+
readonly sinkTimeout?: Duration.Input | undefined;
|
|
2049
|
+
}
|
|
2050
|
+
/**
|
|
2051
|
+
* The check-run → document reconciler's surface.
|
|
2052
|
+
*
|
|
2053
|
+
* @public
|
|
2054
|
+
*/
|
|
2055
|
+
interface CheckDocumentShape {
|
|
2056
|
+
/**
|
|
2057
|
+
* Record a check's current state and schedule a reconcile.
|
|
2058
|
+
*
|
|
2059
|
+
* @remarks
|
|
2060
|
+
* Never fails and never blocks on the write — the state lands in the
|
|
2061
|
+
* registry, and the debounced background pass projects it. Reporting the
|
|
2062
|
+
* same key again replaces the entry; resolution is **not** terminal, so
|
|
2063
|
+
* `pass` followed by `fail` leaves `fail` even inside one debounce window.
|
|
2064
|
+
*/
|
|
2065
|
+
readonly report: (check: string, report: CheckReport) => Effect.Effect<void>;
|
|
2066
|
+
/** The registry as of now, in first-report order. */
|
|
2067
|
+
readonly checks: Effect.Effect<ReadonlyMap<string, CheckReport>>;
|
|
2068
|
+
/**
|
|
2069
|
+
* Reconcile immediately, skipping the debounce.
|
|
2070
|
+
*
|
|
2071
|
+
* @remarks
|
|
2072
|
+
* Rendering unchanged state issues no write. Call it at the end of a run;
|
|
2073
|
+
* the layer's finalizer also runs it, so the last burst of reports lands
|
|
2074
|
+
* even when the scope closes inside the quiet window.
|
|
2075
|
+
*/
|
|
2076
|
+
readonly flush: Effect.Effect<void, CheckDocumentError>;
|
|
2077
|
+
}
|
|
2078
|
+
declare const CheckDocument_base: Context.ServiceClass<CheckDocument, "@effected/github-actions/CheckDocument", CheckDocumentShape>;
|
|
2079
|
+
/**
|
|
2080
|
+
* A living document of check state: an in-process registry the run reports
|
|
2081
|
+
* into, debounced onto a marker-delimited document, written through a narrow
|
|
2082
|
+
* sink.
|
|
2083
|
+
*
|
|
2084
|
+
* @remarks
|
|
2085
|
+
* **Push, not pull.** The run owns its checks and knows when they resolve;
|
|
2086
|
+
* nothing here polls GitHub. Consumers call `report` as states change, and a
|
|
2087
|
+
* background fiber projects the registry onto a {@link ManagedDocument} —
|
|
2088
|
+
* regions replaced from current state, so a check that resolves many times
|
|
2089
|
+
* updates its region in place instead of appending.
|
|
2090
|
+
*
|
|
2091
|
+
* The debounce is **trailing with a max-wait, never leading**: a burst of
|
|
2092
|
+
* reports coalesces into one write carrying the *final* state, and a steady
|
|
2093
|
+
* stream still surfaces progress every `maxWait`. A pass that renders
|
|
2094
|
+
* byte-identical text issues no write at all.
|
|
2095
|
+
*
|
|
2096
|
+
* `layer` mints fresh state per call — one layer per document. Bind it to a
|
|
2097
|
+
* `const` if two parts of a program must share one registry.
|
|
2098
|
+
*
|
|
2099
|
+
* @example
|
|
2100
|
+
* ```ts
|
|
2101
|
+
* import { CheckDocument, CheckReport, GitHubMarkdown } from "@effected/github-actions";
|
|
2102
|
+
* import { Effect } from "effect";
|
|
2103
|
+
*
|
|
2104
|
+
* const layer = CheckDocument.layer({
|
|
2105
|
+
* namespace: "my-action",
|
|
2106
|
+
* key: "release-validation",
|
|
2107
|
+
* render: (checks) => [
|
|
2108
|
+
* [
|
|
2109
|
+
* "header",
|
|
2110
|
+
* GitHubMarkdown.table(
|
|
2111
|
+
* ["Check", "Outcome"],
|
|
2112
|
+
* [...checks].map(([key, check]) => [key, check.outcome ?? check.state]),
|
|
2113
|
+
* ),
|
|
2114
|
+
* ],
|
|
2115
|
+
* ],
|
|
2116
|
+
* sink: (rendered) => Effect.log(rendered),
|
|
2117
|
+
* });
|
|
2118
|
+
*
|
|
2119
|
+
* const program = Effect.gen(function* () {
|
|
2120
|
+
* const doc = yield* CheckDocument;
|
|
2121
|
+
* yield* doc.report("build", CheckReport.make({ state: "running" }));
|
|
2122
|
+
* yield* doc.report("build", CheckReport.make({ state: "pass", outcome: "clean" }));
|
|
2123
|
+
* yield* doc.flush;
|
|
2124
|
+
* });
|
|
2125
|
+
* ```
|
|
2126
|
+
*
|
|
2127
|
+
* @public
|
|
2128
|
+
*/
|
|
2129
|
+
declare class CheckDocument extends CheckDocument_base {
|
|
2130
|
+
/**
|
|
2131
|
+
* The reconciler over one document.
|
|
2132
|
+
*
|
|
2133
|
+
* @remarks
|
|
2134
|
+
* Forks the debounce fiber into the layer's scope and registers a
|
|
2135
|
+
* finalizer that flushes once more on the way out, so the scope closing
|
|
2136
|
+
* mid-window cannot strand the final state. A background pass that fails
|
|
2137
|
+
* logs a structured warning and leaves the registry intact — the next
|
|
2138
|
+
* report retries it; only `flush` surfaces the typed error.
|
|
2139
|
+
*/
|
|
2140
|
+
static layer(options: CheckDocumentOptions): Layer.Layer<CheckDocument>;
|
|
2141
|
+
/** An inert double; unstubbed members die naming themselves. */
|
|
2142
|
+
static readonly makeTest: (overrides?: Partial<CheckDocumentShape>) => CheckDocumentShape;
|
|
2143
|
+
/** {@link CheckDocument.makeTest} behind a `Layer`. */
|
|
2144
|
+
static readonly layerTest: (overrides?: Partial<CheckDocumentShape>) => Layer.Layer<CheckDocument>;
|
|
2145
|
+
}
|
|
2146
|
+
//#endregion
|
|
2147
|
+
//#region src/CheckState.d.ts
|
|
2148
|
+
/**
|
|
2149
|
+
* The kit's check-state vocabulary.
|
|
2150
|
+
*
|
|
2151
|
+
* @remarks
|
|
2152
|
+
* Deliberately **wider than GitHub's own check-run conclusions**: `running` is
|
|
2153
|
+
* a first-class state rather than the absence of a conclusion, and
|
|
2154
|
+
* `user_interaction_required` names a release pipeline waiting on a human. A
|
|
2155
|
+
* check's lifecycle is a *sequence* of these states, and only the last one is
|
|
2156
|
+
* authoritative — resolution is not a terminal transition, so a check may run
|
|
2157
|
+
* `running`, `pass`, `running`, `fail` in order, and that means `fail`.
|
|
2158
|
+
*
|
|
2159
|
+
* Every state projects onto GitHub's check-run wire vocabulary through
|
|
2160
|
+
* {@link projectCheckState}. GitHub's `cancelled` conclusion has no
|
|
2161
|
+
* counterpart here on purpose: cancellation is something the runner does *to*
|
|
2162
|
+
* a run, not a state a pipeline reports about its own checks.
|
|
2163
|
+
*
|
|
2164
|
+
* @public
|
|
2165
|
+
*/
|
|
2166
|
+
declare const CheckState: Schema.Literals<readonly ["running", "pass", "fail", "warn", "user_interaction_required", "skipped", "timeout"]>;
|
|
2167
|
+
/**
|
|
2168
|
+
* The type of `CheckState`.
|
|
2169
|
+
*
|
|
2170
|
+
* @public
|
|
2171
|
+
*/
|
|
2172
|
+
type CheckState = typeof CheckState.Type;
|
|
2173
|
+
/**
|
|
2174
|
+
* The check-run conclusions the kit vocabulary can produce.
|
|
2175
|
+
*
|
|
2176
|
+
* @remarks
|
|
2177
|
+
* A subset of GitHub's conclusion set, spelled structurally so a pure
|
|
2178
|
+
* vocabulary module does not put `@effected/github` — and through it the
|
|
2179
|
+
* octokit runtime — on its import graph. A structural assertion in the test
|
|
2180
|
+
* suite pins these literals against `CheckConclusion` in `@effected/github`,
|
|
2181
|
+
* so drift between the two spellings fails a test rather than a consumer.
|
|
2182
|
+
*
|
|
2183
|
+
* @public
|
|
2184
|
+
*/
|
|
2185
|
+
type CheckRunConclusion = "success" | "failure" | "neutral" | "skipped" | "timed_out" | "action_required";
|
|
2186
|
+
/**
|
|
2187
|
+
* A `CheckState` on GitHub's check-run wire: a status, and a conclusion
|
|
2188
|
+
* exactly when the status is `completed`.
|
|
2189
|
+
*
|
|
2190
|
+
* @remarks
|
|
2191
|
+
* A discriminated union rather than two optional fields, because the wire
|
|
2192
|
+
* protocol's own invariant is conditional: an in-progress check run *has* no
|
|
2193
|
+
* conclusion, and a completed one always does.
|
|
2194
|
+
*
|
|
2195
|
+
* @public
|
|
2196
|
+
*/
|
|
2197
|
+
type CheckRunProjection = {
|
|
2198
|
+
readonly status: "in_progress";
|
|
2199
|
+
} | {
|
|
2200
|
+
readonly status: "completed";
|
|
2201
|
+
readonly conclusion: CheckRunConclusion;
|
|
2202
|
+
};
|
|
2203
|
+
/**
|
|
2204
|
+
* Project a kit check state onto GitHub's check-run wire vocabulary.
|
|
2205
|
+
*
|
|
2206
|
+
* @remarks
|
|
2207
|
+
* The canonical mapping: `running` is `in_progress`; everything else is
|
|
2208
|
+
* `completed` with `pass → success`, `fail → failure`, `warn → neutral`
|
|
2209
|
+
* (GitHub has no warning conclusion, and `neutral` is its non-failing,
|
|
2210
|
+
* non-success verdict), `user_interaction_required → action_required`,
|
|
2211
|
+
* `skipped → skipped` and `timeout → timed_out`.
|
|
2212
|
+
*
|
|
2213
|
+
* @public
|
|
2214
|
+
*/
|
|
2215
|
+
declare const projectCheckState: (state: CheckState) => CheckRunProjection;
|
|
2216
|
+
//#endregion
|
|
2217
|
+
//#region src/DetachedProcess.d.ts
|
|
2218
|
+
declare const DetachedProcessError_base: Schema.Class<DetachedProcessError, Schema.TaggedStruct<"DetachedProcessError", {
|
|
2219
|
+
/**
|
|
2220
|
+
* `logUnavailable` — the log file could not be opened, so there is nowhere
|
|
2221
|
+
* for the child's output to go. `spawnFailed` — the child did not start.
|
|
2222
|
+
* `invalidPid` — a non-positive pid was handed to {@link DetachedProcess.reap};
|
|
2223
|
+
* see there for why this is the most important value in the module.
|
|
2224
|
+
* `signalFailed` — the signal was refused, e.g. the process belongs to
|
|
2225
|
+
* another user. `notReady` — the readiness probe never held.
|
|
2226
|
+
*/
|
|
2227
|
+
readonly reason: Schema.Literals<readonly ["logUnavailable", "spawnFailed", "invalidPid", "signalFailed", "notReady"]>;
|
|
2228
|
+
/** The pid involved, when one is. */
|
|
2229
|
+
readonly pid: Schema.optionalKey<Schema.Number>;
|
|
2230
|
+
/** The path involved, when one is. */
|
|
2231
|
+
readonly path: Schema.optionalKey<Schema.String>;
|
|
2232
|
+
/** The underlying failure, preserved structurally. */
|
|
2233
|
+
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
2234
|
+
}>, import("effect/Cause").YieldableError>;
|
|
2235
|
+
/**
|
|
2236
|
+
* Raised when a detached child cannot be started, waited for, or reaped.
|
|
2237
|
+
*
|
|
2238
|
+
* @public
|
|
2239
|
+
*/
|
|
2240
|
+
declare class DetachedProcessError extends DetachedProcessError_base {
|
|
2241
|
+
get message(): string;
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* The schema a pid crosses the phase boundary through.
|
|
2245
|
+
*
|
|
2246
|
+
* @remarks
|
|
2247
|
+
* A pid is persisted in `GITHUB_STATE` by `main` and read back by `post`, which
|
|
2248
|
+
* means it makes the round trip as **text**. This is the boundary check on the
|
|
2249
|
+
* way back in: a truncated file, an absent key or a `Number("")` all decode to
|
|
2250
|
+
* `0`, and `0` is not a process — it is the current process's whole group.
|
|
2251
|
+
* Refusing it here means the bad value never reaches {@link DetachedProcess.reap}
|
|
2252
|
+
* in the first place, and reap's own guard is the second of two defenses rather
|
|
2253
|
+
* than the only one.
|
|
2254
|
+
*
|
|
2255
|
+
* **The brand is core's**, from `ChildProcessSpawner` — the subprocess
|
|
2256
|
+
* vocabulary belongs to core and this package does not get to re-declare it.
|
|
2257
|
+
* What core does not have is a *validating* way to reconstruct one: its
|
|
2258
|
+
* constructor is `Brand.nominal`, which applies no runtime check, so
|
|
2259
|
+
* `ChildProcessSpawner.ProcessId(0)` succeeds. That is exactly right for a pid
|
|
2260
|
+
* the spawner just produced, and exactly wrong for a pid that has been through a
|
|
2261
|
+
* text file. This schema is that missing check, and it decodes to core's type so
|
|
2262
|
+
* the two are interchangeable.
|
|
2263
|
+
*
|
|
2264
|
+
* @example
|
|
2265
|
+
* ```ts
|
|
1677
2266
|
* import { ActionState, DetachedProcess, ProcessId } from "@effected/github-actions";
|
|
1678
2267
|
* import { Effect } from "effect";
|
|
1679
2268
|
*
|
|
@@ -1896,6 +2485,230 @@ declare class DryRun extends DryRun_base {
|
|
|
1896
2485
|
static readonly layerTest: (overrides?: Partial<DryRunShape>) => Layer.Layer<DryRun>;
|
|
1897
2486
|
}
|
|
1898
2487
|
//#endregion
|
|
2488
|
+
//#region src/GitHubMarkdown.d.ts
|
|
2489
|
+
/**
|
|
2490
|
+
* A heading level GitHub renders, `1` through `6`.
|
|
2491
|
+
*
|
|
2492
|
+
* @public
|
|
2493
|
+
*/
|
|
2494
|
+
type GitHubHeadingDepth = 1 | 2 | 3 | 4 | 5 | 6;
|
|
2495
|
+
/**
|
|
2496
|
+
* Options for {@link GitHubMarkdown.list}.
|
|
2497
|
+
*
|
|
2498
|
+
* @public
|
|
2499
|
+
*/
|
|
2500
|
+
interface GitHubListOptions {
|
|
2501
|
+
/** Render `1.`-numbered items instead of bullets. */
|
|
2502
|
+
readonly ordered?: boolean | undefined;
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* The row-schema constraint {@link GitHubMarkdown.tableFor} accepts: any
|
|
2506
|
+
* schema exposing a struct field map — `Schema.Struct` and `Schema.Class`
|
|
2507
|
+
* both qualify.
|
|
2508
|
+
*
|
|
2509
|
+
* @public
|
|
2510
|
+
*/
|
|
2511
|
+
type GitHubRowSchema = Schema.Constraint & {
|
|
2512
|
+
readonly fields: Schema.Struct.Fields;
|
|
2513
|
+
};
|
|
2514
|
+
/**
|
|
2515
|
+
* The field keys of a row schema whose column REQUIRES an explicit
|
|
2516
|
+
* `format`: fields whose encoded side is not a string (their codec has no
|
|
2517
|
+
* string projection to borrow), and fields whose encoding needs services
|
|
2518
|
+
* (a sync cell render cannot provide them).
|
|
2519
|
+
*
|
|
2520
|
+
* @public
|
|
2521
|
+
*/
|
|
2522
|
+
type GitHubSchemaTableFormatRequiredKeys<Fields extends Schema.Struct.Fields> = { [K in keyof Fields]: [Fields[K]["Encoded"]] extends [string | undefined] ? [Fields[K]["EncodingServices"]] extends [never] ? never : K : K; }[keyof Fields];
|
|
2523
|
+
/**
|
|
2524
|
+
* Per-column configuration for {@link GitHubMarkdown.tableFor}.
|
|
2525
|
+
*
|
|
2526
|
+
* @public
|
|
2527
|
+
*/
|
|
2528
|
+
interface GitHubSchemaTableColumn<Value> {
|
|
2529
|
+
/**
|
|
2530
|
+
* The column header, overriding the field schema's `title` annotation
|
|
2531
|
+
* and the field-name fallback. Pre-rendered markdown, like every cell.
|
|
2532
|
+
*/
|
|
2533
|
+
readonly header?: string | undefined;
|
|
2534
|
+
/**
|
|
2535
|
+
* Render a cell from the decoded field value instead of encoding it
|
|
2536
|
+
* through the field's codec. Required — by type — for a field whose
|
|
2537
|
+
* encoded side is not a string.
|
|
2538
|
+
*/
|
|
2539
|
+
readonly format?: ((value: Value) => string) | undefined;
|
|
2540
|
+
}
|
|
2541
|
+
/**
|
|
2542
|
+
* {@link GitHubSchemaTableColumn} with the `format` obligation discharged —
|
|
2543
|
+
* the entry shape a non-string-encoded field demands.
|
|
2544
|
+
*
|
|
2545
|
+
* @public
|
|
2546
|
+
*/
|
|
2547
|
+
interface GitHubSchemaTableFormattedColumn<Value> extends GitHubSchemaTableColumn<Value> {
|
|
2548
|
+
readonly format: (value: Value) => string;
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* The per-field column map for {@link GitHubMarkdown.tableFor}: entries are
|
|
2552
|
+
* optional except where the field's encoded side is not a string, where the
|
|
2553
|
+
* entry — and its `format` — are required.
|
|
2554
|
+
*
|
|
2555
|
+
* @public
|
|
2556
|
+
*/
|
|
2557
|
+
type GitHubSchemaTableColumns<Fields extends Schema.Struct.Fields> = { readonly [K in GitHubSchemaTableFormatRequiredKeys<Fields>]: GitHubSchemaTableFormattedColumn<Exclude<Fields[K]["Type"], undefined>>; } & { readonly [K in Exclude<keyof Fields, GitHubSchemaTableFormatRequiredKeys<Fields>>]?: GitHubSchemaTableColumn<Exclude<Fields[K]["Type"], undefined>>; };
|
|
2558
|
+
/**
|
|
2559
|
+
* Options for {@link GitHubMarkdown.tableFor}. The whole bag is optional
|
|
2560
|
+
* exactly when every field's encoded side is a string; one field without a
|
|
2561
|
+
* string projection makes `columns` — and the entry carrying its `format` —
|
|
2562
|
+
* required.
|
|
2563
|
+
*
|
|
2564
|
+
* @public
|
|
2565
|
+
*/
|
|
2566
|
+
type GitHubSchemaTableOptions<Fields extends Schema.Struct.Fields> = [GitHubSchemaTableFormatRequiredKeys<Fields>] extends [never] ? {
|
|
2567
|
+
readonly columns?: GitHubSchemaTableColumns<Fields> | undefined;
|
|
2568
|
+
} : {
|
|
2569
|
+
readonly columns: GitHubSchemaTableColumns<Fields>;
|
|
2570
|
+
};
|
|
2571
|
+
/**
|
|
2572
|
+
* A renderer minted by {@link GitHubMarkdown.tableFor}: columns are fixed by
|
|
2573
|
+
* the schema, rows are supplied at each render.
|
|
2574
|
+
*
|
|
2575
|
+
* @public
|
|
2576
|
+
*/
|
|
2577
|
+
interface GitHubSchemaTable<Row> {
|
|
2578
|
+
/**
|
|
2579
|
+
* Render the current rows as a GFM table. Pure and repeatable — identical
|
|
2580
|
+
* rows produce identical output, so re-rendering from changed state is
|
|
2581
|
+
* just calling it again.
|
|
2582
|
+
*/
|
|
2583
|
+
render(rows: ReadonlyArray<Row>): string;
|
|
2584
|
+
}
|
|
2585
|
+
/**
|
|
2586
|
+
* The fluent markdown writer for GitHub surfaces — PR comments, check-run
|
|
2587
|
+
* summaries, job summaries.
|
|
2588
|
+
*
|
|
2589
|
+
* @remarks
|
|
2590
|
+
* Every member takes **pre-rendered markdown** (links, emphasis, emoji — the
|
|
2591
|
+
* caller's fragments pass through verbatim) and returns a `string`, so
|
|
2592
|
+
* compositions read as plain string assembly. What the writer owns is the
|
|
2593
|
+
* *structure*: wherever a fragment could break the construct around it, the
|
|
2594
|
+
* output goes through `@effected/markdown`'s node classes and serializer
|
|
2595
|
+
* rather than string joining. A table cell carrying `>=1 || <2` renders with
|
|
2596
|
+
* its pipes escaped instead of shifting every column after it; a code block
|
|
2597
|
+
* whose content contains a fence gets a longer fence; inline code containing
|
|
2598
|
+
* a backtick gets a wider delimiter; a URL containing spaces or parentheses
|
|
2599
|
+
* is angle-bracketed.
|
|
2600
|
+
*
|
|
2601
|
+
* This module is the package's **only** importer of `@effected/markdown` — a
|
|
2602
|
+
* structural test pins that, on the same terms as the Azure confinement — so
|
|
2603
|
+
* an action that never renders markdown never links the engine.
|
|
2604
|
+
*
|
|
2605
|
+
* @example
|
|
2606
|
+
* ```ts
|
|
2607
|
+
* import { GitHubMarkdown } from "@effected/github-actions";
|
|
2608
|
+
*
|
|
2609
|
+
* const body = [
|
|
2610
|
+
* GitHubMarkdown.heading("Release Validation"),
|
|
2611
|
+
* GitHubMarkdown.table(["Check", "Outcome"], [["build", "✅ passed"]]),
|
|
2612
|
+
* GitHubMarkdown.details("Logs", GitHubMarkdown.codeBlock(log, "text")),
|
|
2613
|
+
* ].join("\n\n");
|
|
2614
|
+
* ```
|
|
2615
|
+
*
|
|
2616
|
+
* @public
|
|
2617
|
+
*/
|
|
2618
|
+
declare class GitHubMarkdown {
|
|
2619
|
+
private constructor();
|
|
2620
|
+
/**
|
|
2621
|
+
* A GFM table.
|
|
2622
|
+
*
|
|
2623
|
+
* @remarks
|
|
2624
|
+
* Cells are pre-rendered markdown; the serializer escapes the pipes GFM
|
|
2625
|
+
* would otherwise read as column breaks. Rows shorter than the header are
|
|
2626
|
+
* padded with empty cells rather than shifting.
|
|
2627
|
+
*/
|
|
2628
|
+
static table(headers: ReadonlyArray<string>, rows: ReadonlyArray<ReadonlyArray<string>>): string;
|
|
2629
|
+
/**
|
|
2630
|
+
* A GFM table whose columns are defined ONCE by a row schema.
|
|
2631
|
+
*
|
|
2632
|
+
* @remarks
|
|
2633
|
+
* The schema is the single authority for the table's shape: column order
|
|
2634
|
+
* is field declaration order, each header is the field's `title`
|
|
2635
|
+
* annotation (fall back: the property name, overridable per column), and
|
|
2636
|
+
* each cell is the field value's **encoded** string form — a branded or
|
|
2637
|
+
* typed field projects through its own codec, so the vocabulary lives
|
|
2638
|
+
* with the schema instead of being respelled at every call site, and a
|
|
2639
|
+
* row can no longer transpose columns because it is a typed object, not
|
|
2640
|
+
* a positional array.
|
|
2641
|
+
*
|
|
2642
|
+
* A field whose encoded side is not a string has no string projection to
|
|
2643
|
+
* borrow; the type of `options` makes its column's `format` — and
|
|
2644
|
+
* therefore `columns` and `options` themselves — required. An absent or
|
|
2645
|
+
* `undefined` optional field renders as an empty cell without consulting
|
|
2646
|
+
* codec or formatter.
|
|
2647
|
+
*
|
|
2648
|
+
* The renderer is a pure value: `render` maps current rows through
|
|
2649
|
+
* {@link GitHubMarkdown.table}, so escaping is inherited and identical
|
|
2650
|
+
* rows produce identical output. Rows are already-decoded values of the
|
|
2651
|
+
* schema's type, so encoding them is total in practice; a value smuggled
|
|
2652
|
+
* past the types throws the codec's `SchemaError` as a defect — same
|
|
2653
|
+
* posture as the serializer arm above, **not** a silent fallback.
|
|
2654
|
+
*
|
|
2655
|
+
* Only string-keyed fields become columns; symbol keys are not
|
|
2656
|
+
* enumerable table columns.
|
|
2657
|
+
*
|
|
2658
|
+
* @example
|
|
2659
|
+
* ```ts
|
|
2660
|
+
* import { GitHubMarkdown } from "@effected/github-actions";
|
|
2661
|
+
* import { Schema } from "effect";
|
|
2662
|
+
*
|
|
2663
|
+
* const CheckRow = Schema.Struct({
|
|
2664
|
+
* name: Schema.String.annotate({ title: "Check" }),
|
|
2665
|
+
* outcome: Schema.Literals(["passed", "failed"]),
|
|
2666
|
+
* });
|
|
2667
|
+
* const checks = GitHubMarkdown.tableFor(CheckRow);
|
|
2668
|
+
* const body = checks.render([{ name: "build", outcome: "passed" }]);
|
|
2669
|
+
* ```
|
|
2670
|
+
*/
|
|
2671
|
+
static tableFor<S extends GitHubRowSchema>(schema: S, ...options: [GitHubSchemaTableFormatRequiredKeys<S["fields"]>] extends [never] ? [options?: GitHubSchemaTableOptions<S["fields"]>] : [options: GitHubSchemaTableOptions<S["fields"]>]): GitHubSchemaTable<S["Type"]>;
|
|
2672
|
+
/** An ATX heading; the level defaults to `2`. */
|
|
2673
|
+
static heading(text: string, level?: GitHubHeadingDepth): string;
|
|
2674
|
+
/** A link. URLs the destination cannot carry raw are angle-bracketed. */
|
|
2675
|
+
static link(text: string, url: string): string;
|
|
2676
|
+
/** Inline code. Content containing backticks widens the delimiter. */
|
|
2677
|
+
static code(text: string): string;
|
|
2678
|
+
/** A fenced code block. Content containing a fence lengthens the fence. */
|
|
2679
|
+
static codeBlock(content: string, language?: string): string;
|
|
2680
|
+
/**
|
|
2681
|
+
* A list of pre-rendered markdown items.
|
|
2682
|
+
*
|
|
2683
|
+
* @remarks
|
|
2684
|
+
* A multi-line item is indented onto continuation lines, so it stays part
|
|
2685
|
+
* of its bullet instead of terminating the list.
|
|
2686
|
+
*/
|
|
2687
|
+
static list(items: ReadonlyArray<string>, options?: GitHubListOptions): string;
|
|
2688
|
+
/**
|
|
2689
|
+
* A collapsible `<details>` block.
|
|
2690
|
+
*
|
|
2691
|
+
* @remarks
|
|
2692
|
+
* mdast has no details node, so this is the one construct the writer emits
|
|
2693
|
+
* as raw HTML. The blank lines around `body` are what make GitHub render
|
|
2694
|
+
* the markdown inside it; `summary` is HTML context — markdown is **not**
|
|
2695
|
+
* rendered there, so bold a summary with `<strong>`, not `**`.
|
|
2696
|
+
*/
|
|
2697
|
+
static details(summary: string, body: string): string;
|
|
2698
|
+
/**
|
|
2699
|
+
* Pre-rendered markdown, passed through by name.
|
|
2700
|
+
*
|
|
2701
|
+
* @remarks
|
|
2702
|
+
* The identity function, deliberately: every writer member already treats
|
|
2703
|
+
* its fragments as markdown, so `raw` adds no behavior — it adds the
|
|
2704
|
+
* *statement* that a value is already rendered. Use it where a fragment
|
|
2705
|
+
* from elsewhere enters a composition and a reader would otherwise wonder
|
|
2706
|
+
* whether it still needs escaping. It replaces the `Html.make` idiom,
|
|
2707
|
+
* which passes markdown through correctly but announces the wrong intent.
|
|
2708
|
+
*/
|
|
2709
|
+
static raw(markdown: string): string;
|
|
2710
|
+
}
|
|
2711
|
+
//#endregion
|
|
1899
2712
|
//#region src/GitHubToken.d.ts
|
|
1900
2713
|
declare const GitHubTokenError_base: Schema.Class<GitHubTokenError, Schema.TaggedStruct<"GitHubTokenError", {
|
|
1901
2714
|
/**
|
|
@@ -2087,167 +2900,183 @@ declare class GitHubToken {
|
|
|
2087
2900
|
static readonly dispose: (options?: ReadOptions | undefined) => Effect.Effect<void, ActionStateError | import("@effected/github").GitHubAppError, ActionState | GitHubApp>;
|
|
2088
2901
|
}
|
|
2089
2902
|
//#endregion
|
|
2090
|
-
//#region src/
|
|
2091
|
-
declare const
|
|
2092
|
-
/**
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
* `missingClaims` — it decoded, but without the claims a provenance statement
|
|
2099
|
-
* needs.
|
|
2100
|
-
*/
|
|
2101
|
-
readonly reason: Schema.Literals<readonly ["unavailable", "requestFailed", "malformedResponse", "malformedToken", "missingClaims"]>;
|
|
2102
|
-
/** What was wrong, in one line. */
|
|
2103
|
-
readonly detail: Schema.optionalKey<Schema.String>;
|
|
2104
|
-
/** The HTTP status, when the token service answered. */
|
|
2105
|
-
readonly status: Schema.optionalKey<Schema.Number>;
|
|
2106
|
-
/** The underlying failure, preserved structurally. */
|
|
2107
|
-
readonly cause: Schema.optionalKey<Schema.Defect>;
|
|
2903
|
+
//#region src/ManagedDocument.d.ts
|
|
2904
|
+
declare const ManagedDocumentError_base: Schema.Class<ManagedDocumentError, Schema.TaggedStruct<"ManagedDocumentError", {
|
|
2905
|
+
/** Which ambiguity or refusal was found. */
|
|
2906
|
+
readonly kind: Schema.Literals<readonly ["unterminatedRegion", "orphanedEnd", "overlappingRegions", "duplicateRegion", "markerInContent", "duplicateDeclaration"]>;
|
|
2907
|
+
/** 1-based line of the offending marker, for the structural kinds. */
|
|
2908
|
+
readonly line: Schema.optionalKey<Schema.Number>;
|
|
2909
|
+
/** The region key involved, when the failure names one. */
|
|
2910
|
+
readonly key: Schema.optionalKey<Schema.String>;
|
|
2108
2911
|
}>, import("effect/Cause").YieldableError>;
|
|
2109
2912
|
/**
|
|
2110
|
-
* Raised when
|
|
2913
|
+
* Raised when a managed document cannot be read or regenerated without
|
|
2914
|
+
* guessing.
|
|
2915
|
+
*
|
|
2916
|
+
* @remarks
|
|
2917
|
+
* The four structural kinds (`unterminatedRegion`, `orphanedEnd`,
|
|
2918
|
+
* `overlappingRegions`, `duplicateRegion`) surface at parse time and name an
|
|
2919
|
+
* ambiguity whose silent resolution would corrupt content a human wrote by
|
|
2920
|
+
* hand. The two declaration kinds surface when regions are applied:
|
|
2921
|
+
* `markerInContent` refuses region content that itself contains a line the
|
|
2922
|
+
* scanner would read as a region marker, and `duplicateDeclaration` refuses
|
|
2923
|
+
* one call that states two intentions for the same region.
|
|
2111
2924
|
*
|
|
2112
2925
|
* @public
|
|
2113
2926
|
*/
|
|
2114
|
-
declare class
|
|
2927
|
+
declare class ManagedDocumentError extends ManagedDocumentError_base {
|
|
2115
2928
|
get message(): string;
|
|
2116
2929
|
}
|
|
2117
|
-
declare const OidcClaims_base: Schema.Class<OidcClaims, Schema.Struct<{
|
|
2118
|
-
/** The issuer, e.g. `https://token.actions.githubusercontent.com`. */
|
|
2119
|
-
readonly iss: Schema.String;
|
|
2120
|
-
/** The full ref the workflow ran on. */
|
|
2121
|
-
readonly ref: Schema.String;
|
|
2122
|
-
/** The commit. */
|
|
2123
|
-
readonly sha: Schema.String;
|
|
2124
|
-
/** `owner/repo`. */
|
|
2125
|
-
readonly repository: Schema.String;
|
|
2126
|
-
/** The event that triggered the run. */
|
|
2127
|
-
readonly event_name: Schema.String;
|
|
2128
|
-
/** The reusable-workflow ref, which is what a verifier pins against. */
|
|
2129
|
-
readonly job_workflow_ref: Schema.String;
|
|
2130
|
-
/** The calling workflow's ref. */
|
|
2131
|
-
readonly workflow_ref: Schema.String;
|
|
2132
|
-
/** The numeric repository id, as a string. */
|
|
2133
|
-
readonly repository_id: Schema.String;
|
|
2134
|
-
/** The numeric owner id, as a string. */
|
|
2135
|
-
readonly repository_owner_id: Schema.String;
|
|
2136
|
-
/** `github-hosted` or `self-hosted`. */
|
|
2137
|
-
readonly runner_environment: Schema.String;
|
|
2138
|
-
/** The run id, as a string. */
|
|
2139
|
-
readonly run_id: Schema.String;
|
|
2140
|
-
/** The run attempt, as a string. */
|
|
2141
|
-
readonly run_attempt: Schema.String;
|
|
2142
|
-
}>, {}>;
|
|
2143
2930
|
/**
|
|
2144
|
-
*
|
|
2145
|
-
*
|
|
2146
|
-
* @remarks
|
|
2147
|
-
* The field names are GitHub's own JWT claim names, kept verbatim rather than
|
|
2148
|
-
* translated to the kit's casing. They are an **external vocabulary** — the
|
|
2149
|
-
* same strings that appear in a SLSA provenance predicate and in every
|
|
2150
|
-
* published example of an Actions OIDC policy — and renaming them would put a
|
|
2151
|
-
* translation layer between a consumer and the specification they are reading.
|
|
2931
|
+
* Options identifying a managed document inside a text that may not carry one
|
|
2932
|
+
* yet.
|
|
2152
2933
|
*
|
|
2153
2934
|
* @public
|
|
2154
2935
|
*/
|
|
2155
|
-
|
|
2936
|
+
interface ManagedDocumentSource {
|
|
2937
|
+
/** Whose document this is, e.g. your action's name. */
|
|
2938
|
+
readonly namespace: string;
|
|
2939
|
+
/** Which document, within that namespace. */
|
|
2940
|
+
readonly key: string;
|
|
2941
|
+
/**
|
|
2942
|
+
* The current text — a fetched comment body, a PR description — or absent
|
|
2943
|
+
* when there is nothing yet. An absent text and an empty one mean the same
|
|
2944
|
+
* thing: a fresh document.
|
|
2945
|
+
*/
|
|
2946
|
+
readonly text?: string | undefined;
|
|
2947
|
+
}
|
|
2948
|
+
declare const ManagedDocument_base: Schema.Class<ManagedDocument, Schema.Struct<{
|
|
2949
|
+
/** Whose document this is. */
|
|
2950
|
+
readonly namespace: Schema.String;
|
|
2951
|
+
/** Which document, within that namespace. */
|
|
2952
|
+
readonly key: Schema.String;
|
|
2953
|
+
/** The document's full text, sentinel and regions included. */
|
|
2954
|
+
readonly text: Schema.String;
|
|
2955
|
+
}>, {}>;
|
|
2156
2956
|
/**
|
|
2157
|
-
*
|
|
2957
|
+
* A marker-delimited document: named regions a tool owns, inside text a human
|
|
2958
|
+
* may also edit.
|
|
2959
|
+
*
|
|
2960
|
+
* @remarks
|
|
2961
|
+
* The one primitive behind both the sticky PR comment and the managed PR
|
|
2962
|
+
* description. A sentinel HTML comment (`<!-- namespace:key -->`) identifies
|
|
2963
|
+
* the document; each region is delimited by HTML-comment markers keyed
|
|
2964
|
+
* `namespace.key.region`; and everything outside the managed regions is
|
|
2965
|
+
* preserved byte-for-byte on regeneration. Regions are **replaced from
|
|
2966
|
+
* current state, never appended** — applying the same region twice yields one
|
|
2967
|
+
* region carrying the latest content, which is what makes a check that
|
|
2968
|
+
* resolves many times safe to re-render.
|
|
2969
|
+
*
|
|
2970
|
+
* The region engine is `@effected/templates`' pure `SectionDocument` —
|
|
2971
|
+
* reused, not reinvented — fixed to the HTML comment style and a
|
|
2972
|
+
* region-specific phrase. Everything here is string → string; the GitHub
|
|
2973
|
+
* write path composes this with `PullRequestComment` (whose `CommentMarker`
|
|
2974
|
+
* renders the *same* sentinel for the same namespace and key) or a PR-body
|
|
2975
|
+
* update in `@effected/github`.
|
|
2976
|
+
*
|
|
2977
|
+
* Construct with {@link ManagedDocument.parseResult} — create-or-update in
|
|
2978
|
+
* one call, so the consumer never branches on whether the document exists
|
|
2979
|
+
* yet. `ManagedDocument.make` is the raw schema constructor and performs no
|
|
2980
|
+
* structural validation.
|
|
2981
|
+
*
|
|
2982
|
+
* @example
|
|
2983
|
+
* ```ts
|
|
2984
|
+
* import { ManagedDocument } from "@effected/github-actions";
|
|
2985
|
+
* import { Result } from "effect";
|
|
2986
|
+
*
|
|
2987
|
+
* const doc = ManagedDocument.parseResult({ namespace: "my-action", key: "release", text: fetched });
|
|
2988
|
+
* if (Result.isSuccess(doc)) {
|
|
2989
|
+
* const next = doc.success.withRegionsResult([
|
|
2990
|
+
* ["header", "## Validating Release"],
|
|
2991
|
+
* ["footer", "generated by my-action"],
|
|
2992
|
+
* ]);
|
|
2993
|
+
* }
|
|
2994
|
+
* ```
|
|
2158
2995
|
*
|
|
2159
2996
|
* @public
|
|
2160
2997
|
*/
|
|
2161
|
-
|
|
2998
|
+
declare class ManagedDocument extends ManagedDocument_base {
|
|
2162
2999
|
/**
|
|
2163
|
-
*
|
|
3000
|
+
* Read a document out of existing text, or begin a fresh one.
|
|
2164
3001
|
*
|
|
2165
3002
|
* @remarks
|
|
2166
|
-
*
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
3003
|
+
* The synchronous primitive; {@link ManagedDocument.parse} derives from it.
|
|
3004
|
+
* Absent text, empty text and text that carries no sentinel are all legal —
|
|
3005
|
+
* the sentinel and regions are added by the first
|
|
3006
|
+
* {@link ManagedDocument.withRegionsResult}. Only a *structurally corrupt*
|
|
3007
|
+
* region layout fails, because every structural ambiguity is a case where
|
|
3008
|
+
* a silent choice would destroy content a human wrote.
|
|
2169
3009
|
*/
|
|
2170
|
-
|
|
3010
|
+
static parseResult(source: ManagedDocumentSource): Result.Result<ManagedDocument, ManagedDocumentError>;
|
|
2171
3011
|
/**
|
|
2172
|
-
*
|
|
3012
|
+
* Read a document out of existing text, in `Effect`.
|
|
2173
3013
|
*
|
|
2174
3014
|
* @remarks
|
|
2175
|
-
*
|
|
2176
|
-
*
|
|
3015
|
+
* Defined in terms of {@link ManagedDocument.parseResult} — synchronous
|
|
3016
|
+
* callers can use that variant directly.
|
|
3017
|
+
*/
|
|
3018
|
+
static readonly parse: (source: ManagedDocumentSource) => Effect.Effect<ManagedDocument, ManagedDocumentError, never>;
|
|
3019
|
+
/** The HTML comment identifying this document, `<!-- namespace:key -->`. */
|
|
3020
|
+
get sentinel(): string;
|
|
3021
|
+
/** Does this text carry the document's sentinel? */
|
|
3022
|
+
matches(text: string): boolean;
|
|
3023
|
+
/** The content of one region, if the document carries it. */
|
|
3024
|
+
region(key: string): Option.Option<string>;
|
|
3025
|
+
/** Every region this document carries, in document order. */
|
|
3026
|
+
get regions(): ReadonlyArray<{
|
|
3027
|
+
readonly key: string;
|
|
3028
|
+
readonly content: string;
|
|
3029
|
+
}>;
|
|
3030
|
+
/**
|
|
3031
|
+
* The document with these regions replaced from current state.
|
|
2177
3032
|
*
|
|
2178
|
-
*
|
|
2179
|
-
*
|
|
2180
|
-
*
|
|
2181
|
-
*
|
|
2182
|
-
*
|
|
2183
|
-
*
|
|
2184
|
-
*
|
|
2185
|
-
*
|
|
2186
|
-
* key endpoint being reachable at attestation time.
|
|
3033
|
+
* @remarks
|
|
3034
|
+
* The synchronous primitive; {@link ManagedDocument.withRegions} derives
|
|
3035
|
+
* from it. Each entry pairs a region key with its full new content. A
|
|
3036
|
+
* region already present is **replaced in place**; a region not present
|
|
3037
|
+
* yet is added; regions not named are left exactly as they are; and every
|
|
3038
|
+
* byte outside a managed region survives untouched. Applying entries that
|
|
3039
|
+
* change nothing returns byte-identical text, which is what lets a caller
|
|
3040
|
+
* compare-and-skip instead of issuing a write.
|
|
2187
3041
|
*
|
|
2188
|
-
*
|
|
2189
|
-
*
|
|
3042
|
+
* Region keys share the name grammar `namespace` and `key` obey; a key
|
|
3043
|
+
* outside it is a wiring error and throws at construction rather than
|
|
3044
|
+
* surfacing in the typed channel.
|
|
3045
|
+
*/
|
|
3046
|
+
withRegionsResult(entries: ReadonlyArray<readonly [key: string, content: string]>): Result.Result<ManagedDocument, ManagedDocumentError>;
|
|
3047
|
+
/**
|
|
3048
|
+
* The document with these regions replaced, in `Effect`.
|
|
2190
3049
|
*
|
|
2191
|
-
*
|
|
2192
|
-
*
|
|
2193
|
-
*
|
|
2194
|
-
* the synthetic non-JWT its predecessor returned made every consumer's
|
|
2195
|
-
* `decodeJwtClaims` yield nothing and silently skipped the path under test.
|
|
3050
|
+
* @remarks
|
|
3051
|
+
* Defined in terms of {@link ManagedDocument.withRegionsResult} —
|
|
3052
|
+
* synchronous callers can use that variant directly.
|
|
2196
3053
|
*/
|
|
2197
|
-
readonly
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
/**
|
|
2201
|
-
|
|
2202
|
-
*
|
|
2203
|
-
* @remarks
|
|
2204
|
-
* Lives here rather than with attestation because it reads
|
|
2205
|
-
* `ACTIONS_ID_TOKEN_REQUEST_TOKEN` and `ACTIONS_ID_TOKEN_REQUEST_URL`, which
|
|
2206
|
-
* exist only when a workflow declares `permissions: id-token: write` — that is
|
|
2207
|
-
* a fact about the runner, not about signing.
|
|
2208
|
-
*
|
|
2209
|
-
* @example
|
|
2210
|
-
* ```ts
|
|
2211
|
-
* import { OidcTokenIssuer } from "@effected/github-actions";
|
|
2212
|
-
* import { Effect } from "effect";
|
|
2213
|
-
*
|
|
2214
|
-
* const program = Effect.gen(function* () {
|
|
2215
|
-
* const issuer = yield* OidcTokenIssuer;
|
|
2216
|
-
* const claims = yield* issuer.claims("sigstore");
|
|
2217
|
-
* return claims.job_workflow_ref;
|
|
2218
|
-
* });
|
|
2219
|
-
* ```
|
|
2220
|
-
*
|
|
2221
|
-
* @public
|
|
2222
|
-
*/
|
|
2223
|
-
declare class OidcTokenIssuer extends OidcTokenIssuer_base {
|
|
2224
|
-
static readonly layer: Layer.Layer<OidcTokenIssuer, never, ActionEnvironment | HttpClient.HttpClient>;
|
|
3054
|
+
withRegions(entries: ReadonlyArray<readonly [key: string, content: string]>): Effect.Effect<ManagedDocument, ManagedDocumentError>;
|
|
3055
|
+
/** The marker key a region is written under: `namespace.key.region`. */
|
|
3056
|
+
private wireKey;
|
|
3057
|
+
/** The region key back out of a wire key, for error reporting. */
|
|
3058
|
+
private regionKeyOf;
|
|
2225
3059
|
/**
|
|
2226
|
-
*
|
|
3060
|
+
* This document's own regions, in document order.
|
|
2227
3061
|
*
|
|
2228
3062
|
* @remarks
|
|
2229
|
-
*
|
|
2230
|
-
*
|
|
2231
|
-
*
|
|
2232
|
-
*
|
|
2233
|
-
*
|
|
3063
|
+
* A document a human already edited can be structurally corrupt, and a
|
|
3064
|
+
* read has no error channel worth having — a corrupt document simply has
|
|
3065
|
+
* no readable regions; {@link ManagedDocument.parseResult} is where
|
|
3066
|
+
* corruption fails typed. Regions belonging to a *different* document in
|
|
3067
|
+
* the same text (another namespace or key) are not this document's and are
|
|
3068
|
+
* never reported.
|
|
2234
3069
|
*/
|
|
2235
|
-
|
|
2236
|
-
/** A test double. Unstubbed members die rather than answering with a non-token. */
|
|
2237
|
-
static readonly makeTest: (overrides?: Partial<OidcTokenIssuerShape>) => OidcTokenIssuerShape;
|
|
2238
|
-
/** {@link OidcTokenIssuer.makeTest} behind `Layer.succeed`. */
|
|
2239
|
-
static readonly layerTest: (overrides?: Partial<OidcTokenIssuerShape>) => Layer.Layer<OidcTokenIssuer>;
|
|
3070
|
+
private ownRegions;
|
|
2240
3071
|
/**
|
|
2241
|
-
*
|
|
3072
|
+
* Append the sentinel when the text does not carry it yet.
|
|
2242
3073
|
*
|
|
2243
3074
|
* @remarks
|
|
2244
|
-
*
|
|
2245
|
-
*
|
|
2246
|
-
*
|
|
2247
|
-
* members can disagree is how a test proves a path works while production
|
|
2248
|
-
* takes the other one.
|
|
3075
|
+
* Appended at the end — the same position `PullRequestComment.upsert`
|
|
3076
|
+
* writes its marker to — so a document rendered here and a comment written
|
|
3077
|
+
* there agree about where the identity line lives.
|
|
2249
3078
|
*/
|
|
2250
|
-
|
|
3079
|
+
private ensureSentinel;
|
|
2251
3080
|
}
|
|
2252
3081
|
//#endregion
|
|
2253
3082
|
//#region src/Secret.d.ts
|
|
@@ -2316,6 +3145,19 @@ declare class Secret {
|
|
|
2316
3145
|
* over a `Redacted`, so a signing key has to become a string somewhere, and
|
|
2317
3146
|
* the point of this module is that "somewhere" is here and nowhere else.
|
|
2318
3147
|
*
|
|
3148
|
+
* Signing named the member; it does not gate it. **Any in-process use that
|
|
3149
|
+
* needs the raw value without writing it to a runner file is this
|
|
3150
|
+
* operation** — handing a key to a library that takes a plain string. The
|
|
3151
|
+
* dividing line is where the value goes, not what it is for: a value
|
|
3152
|
+
* crossing into a **child's** environment is {@link Secret.forChildEnv},
|
|
3153
|
+
* one written to `GITHUB_STATE` or `GITHUB_OUTPUT` is
|
|
3154
|
+
* {@link Secret.forRunnerFile}, and one that stays in this process is this
|
|
3155
|
+
* member. A third-party SDK that reads only the ambient environment is the
|
|
3156
|
+
* hard case: this package never mutates `process.env` (reads are seeded
|
|
3157
|
+
* once through `ActionEnvironment`), so if a consumer chooses that bridge,
|
|
3158
|
+
* the mutation — and its restore discipline — lives in consumer code as
|
|
3159
|
+
* the consumer's own tradeoff, not as a pattern this member recommends.
|
|
3160
|
+
*
|
|
2319
3161
|
* It masks even though the value is never *written* anywhere, and that is
|
|
2320
3162
|
* deliberate rather than superstitious: a signing key that leaks does so
|
|
2321
3163
|
* through something nobody audited — a debug log of outgoing headers, a
|
|
@@ -2463,5 +3305,5 @@ declare class ToolInstaller extends ToolInstaller_base {
|
|
|
2463
3305
|
static readonly layerTest: (overrides?: Partial<ToolInstallerShape>) => Layer.Layer<ToolInstaller>;
|
|
2464
3306
|
}
|
|
2465
3307
|
//#endregion
|
|
2466
|
-
export { Action, ActionCache, ActionCacheError, type ActionCacheShape, ActionEnvironment, ActionEnvironmentError, type ActionEnvironmentShape, ActionInput, ActionLogger, type ActionLoggerShape, ActionOutputError, ActionOutputs, type ActionOutputsShape, type ActionRunOptions, ActionRuntime, type ActionServices, ActionState, ActionStateError, type ActionStateShape, type AnnotationProperties, Artifact, ArtifactError, type ArtifactItem, type ArtifactRef, type ArtifactShape, type Blob, BlobEnvelope, BlobEnvelopeError, BlobStore, BlobStoreError, type BlobStoreShape, BlobTransferError, CacheKey, CacheKeyError, type ClientLayerOptions, type DataBlobTransfer, DetachedProcess, DetachedProcessError, type DetachedSpawnOptions, type DownloadOptions, type DownloadResult, DryRun, type DryRunShape, type ExtractOptions, type FileBlobTransfer, GitHubCacheBlobStore, GitHubContext, GitHubToken, GitHubTokenError, OidcClaims, OidcTokenError, OidcTokenIssuer, type OidcTokenIssuerShape, ProcessId, type ProvisionOptions, type ReadOptions, type ReadinessOptions, RunnerContext, type S3Config, Secret, ToolInstaller, ToolInstallerError, type ToolInstallerShape, type UploadOptions, type UploadResult, WorkflowCommand, describeCause };
|
|
3308
|
+
export { Action, ActionCache, ActionCacheError, type ActionCacheShape, ActionEnvironment, ActionEnvironmentError, type ActionEnvironmentShape, ActionInput, ActionLogger, type ActionLoggerShape, ActionOutputError, ActionOutputs, type ActionOutputsShape, type ActionRunOptions, ActionRuntime, type ActionServices, ActionState, ActionStateError, type ActionStateShape, ActionsIdentityToken, ActionsProvenance, type AnnotationProperties, Artifact, ArtifactError, type ArtifactItem, type ArtifactRef, type ArtifactShape, type Blob, BlobEnvelope, BlobEnvelopeError, BlobStore, BlobStoreError, type BlobStoreShape, BlobTransferError, CacheKey, CacheKeyError, CheckDocument, CheckDocumentError, type CheckDocumentOptions, type CheckDocumentShape, type CheckDocumentSink, CheckReport, type CheckRunConclusion, type CheckRunProjection, CheckState, type ClientLayerOptions, type DataBlobTransfer, DetachedProcess, DetachedProcessError, type DetachedSpawnOptions, type DownloadOptions, type DownloadResult, DryRun, type DryRunShape, type ExtractOptions, type FileBlobTransfer, GitHubCacheBlobStore, GitHubContext, type GitHubHeadingDepth, type GitHubListOptions, GitHubMarkdown, type GitHubRowSchema, type GitHubSchemaTable, type GitHubSchemaTableColumn, type GitHubSchemaTableColumns, type GitHubSchemaTableFormatRequiredKeys, type GitHubSchemaTableFormattedColumn, type GitHubSchemaTableOptions, GitHubToken, GitHubTokenError, ManagedDocument, ManagedDocumentError, type ManagedDocumentSource, OidcClaims, OidcTokenError, OidcTokenIssuer, type OidcTokenIssuerShape, ProcessId, type ProvisionOptions, type ReadOptions, type ReadinessOptions, RunnerContext, type S3Config, Secret, ToolInstaller, ToolInstallerError, type ToolInstallerShape, type UploadOptions, type UploadResult, type WithBufferOptions, WorkflowCommand, describeCause, projectCheckState };
|
|
2467
3309
|
//# sourceMappingURL=index.d.ts.map
|