fix: make trusted publisher environment optional (#1489)

* fix: make trusted publisher environment optional

* fix: avoid env mismatch on unpinned trusted publishes

---------

Co-authored-by: Onur <onur@solmaz.io>
This commit is contained in:
Onur
2026-04-02 17:20:40 +02:00
committed by GitHub
co-authored by Onur
parent 65bc5d3335
commit 78d0a637fa
16 changed files with 369 additions and 40 deletions
+145
View File
@@ -3582,6 +3582,82 @@ describe("httpApiV1 handlers", () => {
);
});
it("mints a short-lived publish token without environment when none is pinned", async () => {
vi.mocked(verifyGitHubActionsTrustedPublishJwt).mockResolvedValue({
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
environment: "clawhub-release",
runId: "101",
runAttempt: "1",
sha: "abc123",
ref: "refs/heads/main",
refType: "branch",
actor: "onur",
actorId: "42",
} as never);
const runMutation = vi.fn(async (_mutation: unknown, args: Record<string, unknown>) => {
if ("key" in args) return okRate();
return "mutation:ok";
});
const runQuery = vi.fn(async (_query: unknown, args: Record<string, unknown>) => {
if ("name" in args) {
return {
_id: "packages:1",
name: "@openclaw/demo-plugin",
ownerUserId: "users:owner",
};
}
if ("packageId" in args) {
return {
_id: "packageTrustedPublishers:1",
packageId: "packages:1",
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
};
}
return null;
});
const response = await __handlers.mintPublishTokenV1Handler(
makeCtx({ runQuery, runMutation }),
new Request("https://example.com/api/v1/publish/token/mint", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
packageName: "@openclaw/demo-plugin",
version: "1.0.0",
githubOidcToken: "gh.jwt",
}),
}),
);
if (response.status !== 200) throw new Error(await response.text());
const body = await response.json();
expect(body.token).toEqual(expect.any(String));
expect(body.expiresAt).toEqual(expect.any(Number));
const createCall = runMutation.mock.calls.find(
([, args]) => typeof args === "object" && args !== null && "packageId" in args && "tokenHash" in args,
);
expect(createCall?.[1]).toEqual(
expect.objectContaining({
packageId: "packages:1",
version: "1.0.0",
repository: "openclaw/openclaw",
workflowFilename: "plugin-clawhub-release.yml",
runId: "101",
sha: "abc123",
}),
);
expect(createCall?.[1]).not.toHaveProperty("environment");
});
it("sets trusted publisher config for a package", async () => {
vi.mocked(requireApiTokenUser).mockResolvedValue({
userId: "users:1",
@@ -3641,6 +3717,75 @@ describe("httpApiV1 handlers", () => {
);
});
it("sets trusted publisher config for a package without environment", async () => {
vi.mocked(requireApiTokenUser).mockResolvedValue({
userId: "users:1",
user: { _id: "users:1", handle: "p" },
} as never);
vi.mocked(fetchGitHubRepositoryIdentity).mockResolvedValue({
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
} as never);
const runMutation = vi.fn(async (_mutation: unknown, args: Record<string, unknown>) => {
if ("key" in args) return okRate();
return {
_id: "packageTrustedPublishers:1",
packageId: "packages:1",
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
};
});
const response = await __handlers.packagesPostRouterV1Handler(
makeCtx({ runMutation }),
new Request(
"https://example.com/api/v1/packages/%40openclaw%2Fdemo-plugin/trusted-publisher",
{
method: "POST",
headers: {
Authorization: "Bearer clh_test",
"content-type": "application/json",
},
body: JSON.stringify({
repository: "https://github.com/openclaw/openclaw",
workflowFilename: "plugin-clawhub-release.yml",
}),
},
),
);
if (response.status !== 200) throw new Error(await response.text());
expect(fetchGitHubRepositoryIdentity).toHaveBeenCalledWith("https://github.com/openclaw/openclaw");
expect(await response.json()).toEqual({
trustedPublisher: {
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
},
});
const setCall = runMutation.mock.calls.find(
([, args]) => typeof args === "object" && args !== null && "packageName" in args && "actorUserId" in args,
);
expect(setCall?.[1]).toEqual(
expect.objectContaining({
actorUserId: "users:1",
packageName: "@openclaw/demo-plugin",
repository: "openclaw/openclaw",
workflowFilename: "plugin-clawhub-release.yml",
}),
);
expect(setCall?.[1]).not.toHaveProperty("environment");
});
it("deletes trusted publisher config for a package", async () => {
vi.mocked(requireApiTokenUser).mockResolvedValue({
userId: "users:1",
+8 -8
View File
@@ -167,7 +167,7 @@ type PackageTrustedPublisherLike = {
repositoryOwner: string;
repositoryOwnerId: string;
workflowFilename: string;
environment: string;
environment?: string;
createdAt: number;
updatedAt: number;
};
@@ -186,7 +186,7 @@ function toPublicTrustedPublisher(trustedPublisher: PackageTrustedPublisherLike
repositoryOwner: trustedPublisher.repositoryOwner,
repositoryOwnerId: trustedPublisher.repositoryOwnerId,
workflowFilename: trustedPublisher.workflowFilename,
environment: trustedPublisher.environment,
...(trustedPublisher.environment ? { environment: trustedPublisher.environment } : {}),
};
}
@@ -713,7 +713,7 @@ export async function mintPublishTokenV1Handler(ctx: ActionCtx, request: Request
repositoryOwner: trustedPublisher.repositoryOwner,
repositoryOwnerId: trustedPublisher.repositoryOwnerId,
workflowFilename: trustedPublisher.workflowFilename,
environment: trustedPublisher.environment,
...(trustedPublisher.environment ? { environment: trustedPublisher.environment } : {}),
});
const { token, prefix } = generateToken();
const tokenHash = await hashToken(token);
@@ -730,7 +730,7 @@ export async function mintPublishTokenV1Handler(ctx: ActionCtx, request: Request
repositoryOwner: verified.repositoryOwner,
repositoryOwnerId: verified.repositoryOwnerId,
workflowFilename: verified.workflowFilename,
environment: verified.environment,
...(trustedPublisher.environment ? { environment: trustedPublisher.environment } : {}),
runId: verified.runId,
runAttempt: verified.runAttempt,
sha: verified.sha,
@@ -749,7 +749,7 @@ export async function mintPublishTokenV1Handler(ctx: ActionCtx, request: Request
version: payload.version,
repository: verified.repository,
workflowFilename: verified.workflowFilename,
environment: verified.environment,
...(verified.environment ? { environment: verified.environment } : {}),
runId: verified.runId,
runAttempt: verified.runAttempt,
sha: verified.sha,
@@ -768,7 +768,7 @@ export async function mintPublishTokenV1Handler(ctx: ActionCtx, request: Request
version: payload.version,
repository: trustedPublisher.repository,
workflowFilename: trustedPublisher.workflowFilename,
environment: trustedPublisher.environment,
...(trustedPublisher.environment ? { environment: trustedPublisher.environment } : {}),
decision: "rejected",
reason: error instanceof Error ? error.message : "Token verification failed",
},
@@ -798,7 +798,7 @@ export async function packagesPostRouterV1Handler(ctx: ActionCtx, request: Reque
) as {
repository: string;
workflowFilename: string;
environment: string;
environment?: string;
};
const repositoryIdentity = await fetchGitHubRepositoryIdentity(body.repository);
const trustedPublisher = await runMutationRef<PackageTrustedPublisherLike | null>(
@@ -812,7 +812,7 @@ export async function packagesPostRouterV1Handler(ctx: ActionCtx, request: Reque
repositoryOwner: repositoryIdentity.repositoryOwner,
repositoryOwnerId: repositoryIdentity.repositoryOwnerId,
workflowFilename: body.workflowFilename,
environment: body.environment,
...(body.environment ? { environment: body.environment } : {}),
},
);
return json({ trustedPublisher: toPublicTrustedPublisher(trustedPublisher) }, 200, rate.headers);
+49
View File
@@ -15,6 +15,10 @@ const trustedPublisher: TrustedGitHubActionsPublisher = {
workflowFilename: "plugin-clawhub-release.yml",
environment: "clawhub-plugin-release",
};
const trustedPublisherWithoutEnvironment: TrustedGitHubActionsPublisher = {
...trustedPublisher,
environment: undefined,
};
const signingKeyPairPromise = crypto.subtle.generateKey(
{
name: "RSASSA-PKCS1-v1_5",
@@ -84,6 +88,51 @@ describe("verifyGitHubActionsTrustedPublishJwt", () => {
});
});
it("accepts a valid GitHub Actions token when no environment is pinned", async () => {
const { token, jwks } = await createSignedToken({
repository: trustedPublisher.repository,
repository_id: trustedPublisher.repositoryId,
repository_owner: trustedPublisher.repositoryOwner,
repository_owner_id: trustedPublisher.repositoryOwnerId,
workflow_ref:
"openclaw/openclaw/.github/workflows/plugin-clawhub-release.yml@refs/heads/main",
runner_environment: "github-hosted",
event_name: "workflow_dispatch",
workflow: "Plugin ClawHub Release",
sha: "deadbeef",
ref: "refs/heads/main",
ref_type: "branch",
actor: "onur",
actor_id: "42",
run_id: "100",
run_attempt: "2",
iss: "https://token.actions.githubusercontent.com",
aud: "clawhub",
exp: Math.floor(Date.now() / 1000) + 300,
iat: Math.floor(Date.now() / 1000) - 5,
});
const identity = await verifyGitHubActionsTrustedPublishJwt(token, trustedPublisherWithoutEnvironment, {
fetchImpl: async () =>
new Response(JSON.stringify({ keys: [jwks] }), {
status: 200,
headers: { "Content-Type": "application/json" },
}),
});
expect(identity).toMatchObject({
repository: trustedPublisher.repository,
repositoryId: trustedPublisher.repositoryId,
repositoryOwner: trustedPublisher.repositoryOwner,
repositoryOwnerId: trustedPublisher.repositoryOwnerId,
workflowFilename: trustedPublisher.workflowFilename,
runId: "100",
runAttempt: "2",
sha: "deadbeef",
});
expect(identity.environment).toBeUndefined();
});
it("rejects reusable workflow tokens", async () => {
const { token, jwks } = await createSignedToken({
repository: trustedPublisher.repository,
+8 -8
View File
@@ -16,7 +16,7 @@ export type TrustedGitHubActionsPublisher = {
repositoryOwner: string;
repositoryOwnerId: string;
workflowFilename: string;
environment: string;
environment?: string;
};
export type VerifiedGitHubActionsIdentity = {
@@ -28,7 +28,7 @@ export type VerifiedGitHubActionsIdentity = {
workflowName: string;
workflowRef: string;
jobWorkflowRef?: string;
environment: string;
environment?: string;
runnerEnvironment: string;
eventName: string;
sha: string;
@@ -123,7 +123,7 @@ export async function verifyGitHubActionsTrustedPublishJwt(
const workflow = parseWorkflowRef(workflowRef, repository);
const jobWorkflowRef = optionalString(payload.job_workflow_ref);
const runnerEnvironment = requireString(payload.runner_environment, "runner_environment");
const environment = requireString(payload.environment, "environment");
const environment = optionalString(payload.environment);
const eventName = requireString(payload.event_name, "event_name");
const workflowName = requireString(payload.workflow, "workflow");
const sha = requireString(payload.sha, "sha");
@@ -171,14 +171,14 @@ export async function verifyGitHubActionsTrustedPublishJwt(
if (runnerEnvironment !== "github-hosted") {
throw new Error(`Only GitHub-hosted runners may mint trusted publish tokens, got ${runnerEnvironment}`);
}
// v1 keeps secretless publishing behind a manual, environment-protected entry
// point. Tag and release automation should keep using the token path for now.
// v1 keeps secretless publishing behind a manual entry point. Environment
// pinning is optional, but if configured it must match exactly.
if (eventName !== "workflow_dispatch") {
throw new Error(`Trusted publishing requires workflow_dispatch, got ${eventName}`);
}
if (environment !== trustedPublisher.environment) {
if (trustedPublisher.environment && environment !== trustedPublisher.environment) {
throw new Error(
`GitHub OIDC environment mismatch: expected ${trustedPublisher.environment}, got ${environment}`,
`GitHub OIDC environment mismatch: expected ${trustedPublisher.environment}, got ${formatClaimValue(environment ?? "<missing>")}`,
);
}
@@ -191,7 +191,7 @@ export async function verifyGitHubActionsTrustedPublishJwt(
workflowName,
workflowRef,
...(jobWorkflowRef ? { jobWorkflowRef } : {}),
environment,
...(environment ? { environment } : {}),
runnerEnvironment,
eventName,
sha,
+1 -1
View File
@@ -13,7 +13,7 @@ export const createInternal = internalMutation({
repositoryOwner: v.string(),
repositoryOwnerId: v.string(),
workflowFilename: v.string(),
environment: v.string(),
environment: v.optional(v.string()),
runId: v.string(),
runAttempt: v.string(),
sha: v.string(),
+78
View File
@@ -2161,6 +2161,84 @@ describe("packages public queries", () => {
});
});
it("accepts trusted publish tokens when no environment is pinned", async () => {
const runMutation = vi.fn(async (_ref: unknown, args: unknown) => {
if (
typeof args === "object" &&
args !== null &&
"name" in args &&
"version" in args &&
"files" in args
) {
return {
ok: true,
packageId: "packages:demo",
releaseId: "packageReleases:demo-2",
};
}
return null;
});
const trustedPublisher = {
_id: "packageTrustedPublishers:1",
packageId: "packages:demo",
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
};
const ctx = {
runQuery: vi
.fn()
.mockResolvedValueOnce({
_id: "packagePublishTokens:1",
packageId: "packages:demo",
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
version: "1.0.0",
sha: "abc123",
ref: "refs/heads/main",
runId: "100",
runAttempt: "1",
expiresAt: Date.now() + 60_000,
})
.mockResolvedValueOnce(trustedPublisher)
.mockResolvedValueOnce(makePackageDoc({ family: "bundle-plugin" }))
.mockResolvedValueOnce(trustedPublisher)
.mockResolvedValueOnce(null),
runMutation,
scheduler: {
runAfter: vi.fn(),
},
storage: {
get: vi.fn(),
},
};
await expect(
publishPackageForTrustedPublisherInternalHandler(ctx as never, {
publishTokenId: "packagePublishTokens:1",
payload: {
name: "demo-plugin",
family: "bundle-plugin",
version: "1.0.0",
changelog: "init",
bundle: { hostTargets: ["desktop"] },
files: [],
},
}),
).resolves.toMatchObject({
ok: true,
packageId: "packages:demo",
releaseId: "packageReleases:demo-2",
});
});
it("requires manual override for user-auth publishes when trusted publisher config exists", async () => {
const runMutation = vi.fn(async (_ref: unknown, args: unknown) => {
if (
+4 -5
View File
@@ -1306,7 +1306,7 @@ export const setTrustedPublisherForUserInternal = internalMutation({
repositoryOwner: v.string(),
repositoryOwnerId: v.string(),
workflowFilename: v.string(),
environment: v.string(),
environment: v.optional(v.string()),
},
handler: async (ctx, args) => {
const pkg = await getPackageByNormalizedName(ctx, normalizePackageName(args.packageName));
@@ -1317,8 +1317,7 @@ export const setTrustedPublisherForUserInternal = internalMutation({
await requireTrustedPublisherEditor(ctx, pkg, args.actorUserId);
const workflowFilename = normalizeWorkflowFilenameOrThrow(args.workflowFilename);
const environment = args.environment.trim();
if (!environment) throw new ConvexError("Environment is required");
const environment = args.environment?.trim() || undefined;
const existing = await getPackageTrustedPublisherByPackageId(ctx, pkg._id);
const now = Date.now();
@@ -1356,7 +1355,7 @@ export const setTrustedPublisherForUserInternal = internalMutation({
repositoryOwner: args.repositoryOwner,
repositoryOwnerId: args.repositoryOwnerId,
workflowFilename,
environment,
...(environment ? { environment } : {}),
},
createdAt: now,
});
@@ -1635,7 +1634,7 @@ function doesTrustedPublisherMatchPublishToken(
publishToken: Doc<"packagePublishTokens">,
) {
return Boolean(
trustedPublisher &&
trustedPublisher &&
trustedPublisher.packageId === publishToken.packageId &&
trustedPublisher.provider === publishToken.provider &&
trustedPublisher.repository === publishToken.repository &&
+2 -2
View File
@@ -753,7 +753,7 @@ const packageTrustedPublishers = defineTable({
repositoryOwner: v.string(),
repositoryOwnerId: v.string(),
workflowFilename: v.string(),
environment: v.string(),
environment: v.optional(v.string()),
createdByUserId: v.id("users"),
updatedByUserId: v.id("users"),
createdAt: v.number(),
@@ -773,7 +773,7 @@ const packagePublishTokens = defineTable({
repositoryOwner: v.string(),
repositoryOwnerId: v.string(),
workflowFilename: v.string(),
environment: v.string(),
environment: v.optional(v.string()),
runId: v.string(),
runAttempt: v.string(),
sha: v.string(),
+1 -1
View File
@@ -436,7 +436,7 @@ trustedPublisherCmd
.argument("<name>", "Package name")
.requiredOption("--repository <repo>", "GitHub repo (owner/repo or URL)")
.requiredOption("--workflow-filename <file>", "Workflow filename, for example publish.yml")
.requiredOption("--environment <name>", "Protected GitHub environment name")
.option("--environment <name>", "Optional GitHub environment name to pin")
.option("--json", "Output JSON")
.action(async (name, options) => {
const opts = await resolveGlobalOpts();
@@ -1054,6 +1054,26 @@ describe("package commands", () => {
expect(mockLog).toHaveBeenCalledWith("Environment: clawhub-release");
});
it("gets trusted publisher config without a pinned environment", async () => {
httpMocks.apiRequest.mockResolvedValueOnce({
trustedPublisher: {
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
},
});
await cmdGetPackageTrustedPublisher(makeOpts(), "@openclaw/zalo");
expect(mockLog).toHaveBeenCalledWith("Provider: github-actions");
expect(mockLog).toHaveBeenCalledWith("Repository: openclaw/openclaw");
expect(mockLog).toHaveBeenCalledWith("Workflow: plugin-clawhub-release.yml");
expect(mockLog).not.toHaveBeenCalledWith(expect.stringContaining("Environment:"));
});
it("sets trusted publisher config for a package", async () => {
httpMocks.apiRequest.mockResolvedValueOnce({
trustedPublisher: {
@@ -1090,6 +1110,39 @@ describe("package commands", () => {
);
});
it("sets trusted publisher config for a package without environment", async () => {
httpMocks.apiRequest.mockResolvedValueOnce({
trustedPublisher: {
provider: "github-actions",
repository: "openclaw/openclaw",
repositoryId: "1",
repositoryOwner: "openclaw",
repositoryOwnerId: "2",
workflowFilename: "plugin-clawhub-release.yml",
},
});
await cmdSetPackageTrustedPublisher(makeOpts(), "@openclaw/zalo", {
repository: "openclaw/openclaw",
workflowFilename: "plugin-clawhub-release.yml",
});
expect(authTokenMocks.requireAuthToken).toHaveBeenCalled();
expect(httpMocks.apiRequest).toHaveBeenCalledWith(
"https://clawhub.ai",
expect.objectContaining({
method: "POST",
path: "/api/v1/packages/%40openclaw%2Fzalo/trusted-publisher",
token: "tkn",
body: {
repository: "openclaw/openclaw",
workflowFilename: "plugin-clawhub-release.yml",
},
}),
expect.anything(),
);
});
it("deletes trusted publisher config for a package", async () => {
httpMocks.apiRequest.mockResolvedValueOnce({ ok: true });
+10 -5
View File
@@ -83,7 +83,7 @@ type PackageTrustedPublisherGetOptions = {
type PackageTrustedPublisherSetOptions = {
repository: string;
workflowFilename: string;
environment: string;
environment?: string;
json?: boolean;
};
@@ -387,10 +387,9 @@ export async function cmdSetPackageTrustedPublisher(
const trimmed = normalizePackageNameOrFail(packageName);
const repository = options.repository?.trim();
const workflowFilename = options.workflowFilename?.trim();
const environment = options.environment?.trim();
const environment = options.environment?.trim() || undefined;
if (!repository) fail("--repository required");
if (!workflowFilename) fail("--workflow-filename required");
if (!environment) fail("--environment required");
const token = await requireAuthToken();
const registry = await getRegistry(opts, { cache: true });
@@ -402,7 +401,11 @@ export async function cmdSetPackageTrustedPublisher(
method: "POST",
path: `${ApiRoutes.packages}/${encodeURIComponent(trimmed)}/trusted-publisher`,
token,
body: { repository, workflowFilename, environment },
body: {
repository,
workflowFilename,
...(environment ? { environment } : {}),
},
},
ApiV1PackageTrustedPublisherResponseSchema,
);
@@ -643,7 +646,9 @@ function printTrustedPublisher(trustedPublisher: PackageTrustedPublisher) {
console.log(`Provider: ${trustedPublisher.provider}`);
console.log(`Repository: ${trustedPublisher.repository}`);
console.log(`Workflow: ${trustedPublisher.workflowFilename}`);
console.log(`Environment: ${trustedPublisher.environment}`);
if (trustedPublisher.environment) {
console.log(`Environment: ${trustedPublisher.environment}`);
}
}
function printCompatibility(compatibility: PackageCompatibility | null | undefined) {
+2 -2
View File
@@ -122,7 +122,7 @@ export const PackageTrustedPublisherSchema = type({
repositoryOwner: "string",
repositoryOwnerId: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export type PackageTrustedPublisher = (typeof PackageTrustedPublisherSchema)[inferred];
@@ -239,7 +239,7 @@ export type ApiV1PackagePublishResponse = (typeof ApiV1PackagePublishResponseSch
export const PackageTrustedPublisherUpsertRequestSchema = type({
repository: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export type PackageTrustedPublisherUpsertRequest =
(typeof PackageTrustedPublisherUpsertRequestSchema)[inferred];
+3 -3
View File
@@ -116,7 +116,7 @@ export declare const PackageTrustedPublisherSchema: import("arktype/internal/var
repositoryOwner: string;
repositoryOwnerId: string;
workflowFilename: string;
environment: string;
environment?: string | undefined;
}, {}>;
export type PackageTrustedPublisher = (typeof PackageTrustedPublisherSchema)[inferred];
export declare const PackagePublishRequestSchema: import("arktype/internal/variants/object.ts").ObjectType<{
@@ -378,7 +378,7 @@ export type ApiV1PackagePublishResponse = (typeof ApiV1PackagePublishResponseSch
export declare const PackageTrustedPublisherUpsertRequestSchema: import("arktype/internal/variants/object.ts").ObjectType<{
repository: string;
workflowFilename: string;
environment: string;
environment?: string | undefined;
}, {}>;
export type PackageTrustedPublisherUpsertRequest = (typeof PackageTrustedPublisherUpsertRequestSchema)[inferred];
export declare const ApiV1PackageTrustedPublisherResponseSchema: import("arktype/internal/variants/object.ts").ObjectType<{
@@ -389,7 +389,7 @@ export declare const ApiV1PackageTrustedPublisherResponseSchema: import("arktype
repositoryOwner: string;
repositoryOwnerId: string;
workflowFilename: string;
environment: string;
environment?: string | undefined;
} | null;
}, {}>;
export type ApiV1PackageTrustedPublisherResponse = (typeof ApiV1PackageTrustedPublisherResponseSchema)[inferred];
+2 -2
View File
@@ -92,7 +92,7 @@ export const PackageTrustedPublisherSchema = type({
repositoryOwner: "string",
repositoryOwnerId: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export const PackagePublishRequestSchema = type({
name: "string",
@@ -196,7 +196,7 @@ export const ApiV1PackagePublishResponseSchema = type({
export const PackageTrustedPublisherUpsertRequestSchema = type({
repository: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export const ApiV1PackageTrustedPublisherResponseSchema = type({
trustedPublisher: PackageTrustedPublisherSchema.or("null"),
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -122,7 +122,7 @@ export const PackageTrustedPublisherSchema = type({
repositoryOwner: "string",
repositoryOwnerId: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export type PackageTrustedPublisher = (typeof PackageTrustedPublisherSchema)[inferred];
@@ -245,7 +245,7 @@ export type ApiV1PackagePublishResponse = (typeof ApiV1PackagePublishResponseSch
export const PackageTrustedPublisherUpsertRequestSchema = type({
repository: "string",
workflowFilename: "string",
environment: "string",
environment: "string?",
});
export type PackageTrustedPublisherUpsertRequest =
(typeof PackageTrustedPublisherUpsertRequestSchema)[inferred];