diff --git a/.github/workflows/sign-cli.yml b/.github/workflows/sign-cli.yml index 63f6f649a5..43c9906c7a 100644 --- a/.github/workflows/sign-cli.yml +++ b/.github/workflows/sign-cli.yml @@ -34,23 +34,18 @@ jobs: path: packages/opencode/dist/opencode-windows-x64/bin/opencode.exe if-no-files-found: error - # - name: Submit SignPath signing request - # id: submit_signpath_signing_request - # uses: signpath/github-action-submit-signing-request@v1 - # with: - # api-token: ${{ secrets.SIGNPATH_API_KEY }} - # organization-id: ${{ vars.SIGNPATH_ORGANIZATION_ID }} - # project-slug: ${{ vars.SIGNPATH_PROJECT_SLUG }} - # signing-policy-slug: ${{ vars.SIGNPATH_SIGNING_POLICY_SLUG }} - # artifact-configuration-slug: ${{ vars.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }} - # github-artifact-id: ${{ steps.upload_unsigned_windows_cli.outputs.artifact-id }} - # wait-for-completion: true - # output-artifact-directory: signed-opencode-cli + - name: Upload unsigned Windows CLI + id: upload_unsigned_windows_baseline_cli + uses: actions/upload-artifact@v4 + with: + name: unsigned-opencode-windows-baseline-cli + path: packages/opencode/dist/opencode-windows-x64-baseline/bin/opencode.exe + if-no-files-found: error - name: Submit SignPath signing request id: submit_signpath_signing_request run: | - ./script/signpath.ts + ./packages/opencode/script/signpath.ts env: API_TOKEN: ${{ secrets.SIGNPATH_API_KEY }} ORGANIZATION_ID: ${{ vars.SIGNPATH_ORGANIZATION_ID }} @@ -61,6 +56,9 @@ jobs: WAIT_FOR_COMPLETION-for-completion: true OUTPUT_ARTIFACT_DIRECTORY: signed-opencode-cli GITHUB_TOKEN: ${{ github.token }} + INPUT_ARTIFACTS: | + ${{ steps.upload_unsigned_windows_cli.outputs.artifact-id }} + ${{ steps.upload_unsigned_windows_baseline_cli.outputs.artifact-id }} - name: Upload signed Windows CLI uses: actions/upload-artifact@v4 diff --git a/packages/opencode/script/signpath.ts b/packages/opencode/script/signpath.ts new file mode 100644 index 0000000000..1276313a6c --- /dev/null +++ b/packages/opencode/script/signpath.ts @@ -0,0 +1,10 @@ +// import { sign } from "../../../script/signpath.ts" + +console.log(process.env.INPUT_ARTIFACTS) + +// await sign({ +// outputDirectory: optionalEnv("OUTPUT_ARTIFACT_DIRECTORY"), +// }) +// await sign({ +// outputDirectory: optionalEnv("OUTPUT_ARTIFACT_DIRECTORY"), +// }) diff --git a/script/signpath.ts b/script/signpath.ts index 7f5f17c87e..e88aeae457 100755 --- a/script/signpath.ts +++ b/script/signpath.ts @@ -57,6 +57,13 @@ const LogLevelInformation = "Information" const LogLevelWarning = "Warning" const LogLevelError = "Error" +// ── Per-call options ───────────────────────────────────────────────── + +export interface SignOptions { + artifactId: string + outputDirectory: string +} + // ── Input (from env vars) ──────────────────────────────────────────── const connectorUrl = optionalEnv("CONNECTOR_URL", "https://githubactions.connectors.signpath.io") @@ -65,14 +72,12 @@ const organizationId = requiredEnv("ORGANIZATION_ID") const projectSlug = requiredEnv("PROJECT_SLUG") const signingPolicySlug = requiredEnv("SIGNING_POLICY_SLUG") const artifactConfigurationSlug = optionalEnv("ARTIFACT_CONFIGURATION_SLUG") -const githubArtifactId = requiredEnv("GITHUB_ARTIFACT_ID") const gitHubToken = optionalEnv("GITHUB_TOKEN") const parametersRaw = optionalEnv("PARAMETERS") const waitForCompletionTimeoutInSeconds = optionalEnvNumber("WAIT_FOR_COMPLETION_TIMEOUT_IN_SECONDS", 600) const serviceUnavailableTimeoutInSeconds = optionalEnvNumber("SERVICE_UNAVAILABLE_TIMEOUT_IN_SECONDS", 600) const downloadSignedArtifactTimeoutInSeconds = optionalEnvNumber("DOWNLOAD_SIGNED_ARTIFACT_TIMEOUT_IN_SECONDS", 300) const waitForCompletion = optionalEnv("WAIT_FOR_COMPLETION", "true") === "true" -const outputArtifactDirectory = optionalEnv("OUTPUT_ARTIFACT_DIRECTORY") // ── Parse user-defined parameters ──────────────────────────────────── @@ -303,10 +308,13 @@ function redirectConnectorLogsToActionLogs(logs?: Array<{ level: string; message // ── Validation result check ────────────────────────────────────────── -function checkCiSystemValidationResult(validationResult?: SubmitSigningRequestResponse["validationResult"]): void { +function checkCiSystemValidationResult( + artifactId: string, + validationResult?: SubmitSigningRequestResponse["validationResult"], +): void { if (validationResult && validationResult.errors.length > 0) { console.error( - `Build artifact with id "${githubArtifactId}" cannot be signed because of continuous integration system setup validation errors:`, + `Build artifact with id "${artifactId}" cannot be signed because of continuous integration system setup validation errors:`, ) for (const ve of validationResult.errors) { console.error(ve.error) @@ -318,12 +326,12 @@ function checkCiSystemValidationResult(validationResult?: SubmitSigningRequestRe // ── Submit signing request ─────────────────────────────────────────── -async function submitSigningRequest(): Promise { +async function submitSigningRequest(artifactId: string): Promise { const submitUrl = buildSubmitSigningRequestUrl() console.log("Submitting the signing request to SignPath GitHub Actions connector...") const payload = { - artifactId: githubArtifactId, + artifactId, gitHubWorkflowRunId: process.env.GITHUB_RUN_ID, gitHubRepository: process.env.GITHUB_REPOSITORY, gitHubToken: gitHubToken, @@ -344,7 +352,7 @@ async function submitSigningRequest(): Promise { if (!resp.ok) { if (body.error) { redirectConnectorLogsToActionLogs(body.logs) - checkCiSystemValidationResult(body.validationResult) + checkCiSystemValidationResult(artifactId, body.validationResult) throw new Error(body.error) } @@ -363,7 +371,7 @@ async function submitSigningRequest(): Promise { } redirectConnectorLogsToActionLogs(body.logs) - checkCiSystemValidationResult(body.validationResult) + checkCiSystemValidationResult(artifactId, body.validationResult) console.log("SignPath signing request has been successfully submitted") console.log(`The signing request id is ${body.signingRequestId}`) @@ -467,7 +475,7 @@ async function ensureSigningRequestCompleted(signingRequestId: string): Promise< // ── Download signed artifact ───────────────────────────────────────── -async function downloadSignedArtifact(artifactDownloadUrl: string): Promise { +async function downloadSignedArtifact(artifactDownloadUrl: string, outputDirectory: string): Promise { console.log(`Signed artifact url ${artifactDownloadUrl}`) const timeoutMs = downloadSignedArtifactTimeoutInSeconds * 1000 @@ -497,7 +505,7 @@ async function downloadSignedArtifact(artifactDownloadUrl: string): Promise { - try { - const signingRequestId = await submitSigningRequest() +export async function sign(options: SignOptions) { + const signingRequestId = await submitSigningRequest(options.artifactId) - if (waitForCompletion) { - await ensureSigningRequestCompleted(signingRequestId) - if (outputArtifactDirectory) { - await downloadSignedArtifact(buildGetSignedArtifactUrl(signingRequestId)) - } - } else { - await ensureSignPathDownloadedUnsignedArtifact(signingRequestId) + if (waitForCompletion) { + await ensureSigningRequestCompleted(signingRequestId) + if (options.outputDirectory) { + await downloadSignedArtifact(buildGetSignedArtifactUrl(signingRequestId), options.outputDirectory) } - } catch (err: any) { - console.error(err.message) - process.exit(1) + } else { + await ensureSignPathDownloadedUnsignedArtifact(signingRequestId) } } -run() +// ── CLI entry point ────────────────────────────────────────────────── + +if (import.meta.main) { + sign({ + artifactId: requiredEnv("GITHUB_ARTIFACT_ID"), + outputDirectory: optionalEnv("OUTPUT_ARTIFACT_DIRECTORY"), + }).catch((err) => { + console.error(err.message) + process.exit(1) + }) +}