diff --git a/__tests__/resolve-payload-fields.test.ts b/__tests__/resolve-payload-fields.test.ts index d302f6bf..0db6a3c6 100644 --- a/__tests__/resolve-payload-fields.test.ts +++ b/__tests__/resolve-payload-fields.test.ts @@ -1,7 +1,11 @@ import { gzipSync } from 'zlib' /* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ -const { run, toStepOutputs } = require('../scripts/resolve-payload-fields.js') +const { + run, + toStepOutputs, + normalizeForEngine +} = require('../scripts/resolve-payload-fields.js') /* eslint-enable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ const RESOLVER_URL = 'https://resolver.example.com/api' @@ -315,3 +319,54 @@ describe('run with an oversized-payload reference', () => { expect(outputsOf(core).cm_repo_ref).toBe('oversized-payload-reference') }) }) + +describe('normalizeForEngine', () => { + const blob = gzipSync(Buffer.from(JSON.stringify(payload))).toString('base64') + const reference = { + type: 'oversized-payload-reference', + payloadUrl: 'https://resolver.example.com/api/v1/gitstream/payload/key', + resolverToken: 'token', + pullRequestNumber: 7 + } + + it.each([ + ['plain, double-encoded', JSON.stringify(JSON.stringify(payload))], + ['plain, single-encoded', JSON.stringify(payload)], + ['bare base64(gzip)', blob] + ])('passes %s through byte-identical', (_label, raw) => { + expect(normalizeForEngine(raw)).toBe(raw) + }) + + it('hands core the bare blob out of a compressed-payload envelope', () => { + const wrapped = JSON.stringify( + JSON.stringify({ + type: 'compressed-payload', + data: blob, + pullRequestNumber: 7 + }) + ) + + expect(normalizeForEngine(wrapped)).toBe(blob) + }) + + it('hands core a single-encoded reference, which is the depth it parses', () => { + const wrapped = JSON.stringify(JSON.stringify(reference)) + const normalized = normalizeForEngine(wrapped) + + expect(JSON.parse(normalized)).toEqual(reference) + }) + + it('leaves a payload that merely carries a type field alone', () => { + const raw = JSON.stringify(JSON.stringify({ ...payload, type: 'push' })) + + expect(normalizeForEngine(raw)).toBe(raw) + }) + + it('emits the normalized payload as a step output', async () => { + const core = await runWith( + JSON.stringify(JSON.stringify({ type: 'compressed-payload', data: blob })) + ) + + expect(outputsOf(core).client_payload).toBe(blob) + }) +}) diff --git a/action.yml b/action.yml index b13ca13a..a15150f6 100644 --- a/action.yml +++ b/action.yml @@ -73,7 +73,7 @@ runs: env: BASE_REF_ARG: ${{ inputs.base_ref }} HEAD_REF_ARG: ${{ inputs.head_ref }} - PAYLOAD_ARG: ${{ inputs.client_payload }} + PAYLOAD_ARG: ${{ steps.payload-fields.outputs.client_payload }} URL_ARG: ${{ steps.payload-fields.outputs.url }} with: script: | diff --git a/scripts/resolve-payload-fields.js b/scripts/resolve-payload-fields.js index b6686938..717c7ff5 100644 --- a/scripts/resolve-payload-fields.js +++ b/scripts/resolve-payload-fields.js @@ -130,6 +130,25 @@ async function resolvePayload(raw, resolverUrl, core) { return { mode: 'plain', payload: parsePayload(raw) } } +/** + * @param {string} raw the `client_payload` input, verbatim + * @returns {string} the form gitstream-core already understands + */ +function normalizeForEngine(raw) { + const envelope = tryParsePayload(raw) + if (!envelope) { + // Bare base64(gzip), which core inflates on its own. Bitbucket sends this shape today. + return raw + } + if (envelope.type === COMPRESSED_PAYLOAD && envelope.data) { + return envelope.data + } + if (envelope.type === OVERSIZED_PAYLOAD_REFERENCE) { + return JSON.stringify(envelope) + } + return raw +} + /** * Maps a resolved payload to the step outputs. Output values are strings, so * booleans are stringified to be compared as `== 'true'` in step conditions. @@ -156,7 +175,10 @@ async function run({ core, clientPayload, resolverUrl }) { ) core.info(`client_payload mode=${mode}`) - const outputs = toStepOutputs(payload) + const outputs = { + ...toStepOutputs(payload), + client_payload: normalizeForEngine(clientPayload || '') + } if (outputs.github_token) { core.setSecret(outputs.github_token) @@ -171,5 +193,6 @@ async function run({ core, clientPayload, resolverUrl }) { module.exports = { run, - toStepOutputs + toStepOutputs, + normalizeForEngine }