Skip to content

Commit 3b81200

Browse files
etchalonclaude
andcommitted
feat: Re-add secrets-json with var conflict filtering
Secrets that share a name with vars in the wrangler environment config are automatically skipped to avoid Cloudflare API errors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c521254 commit 3b81200

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

action.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ inputs:
3535
description: 'JSON object of environment variables for build step'
3636
required: false
3737
default: '{}'
38+
secrets-json:
39+
description: 'JSON object of secrets to upload to Cloudflare Worker (keys must not overlap with vars in wrangler config)'
40+
required: false
3841
deploy-tag:
3942
description: 'Tag for the deployment (defaults to short SHA)'
4043
required: false
@@ -400,3 +403,61 @@ runs:
400403
401404
# Deploy the version at 100%
402405
npx wrangler versions deploy "${VERSION_ID}@100%" --name "${{ inputs.worker-name }}" -y
406+
407+
- name: Upload secrets to Cloudflare
408+
if: ${{ (inputs.mode == 'full' || inputs.mode == 'deploy') && inputs.secrets-json != '' && inputs.secrets-json != '{}' }}
409+
shell: bash
410+
working-directory: ${{ inputs.working-directory }}
411+
env:
412+
CLOUDFLARE_API_TOKEN: ${{ inputs.cloudflare-api-token }}
413+
CLOUDFLARE_ACCOUNT_ID: ${{ inputs.cloudflare-account-id }}
414+
SECRETS_JSON: ${{ inputs.secrets-json }}
415+
run: |
416+
# Collect var names from wrangler env config to filter out conflicts
417+
VAR_NAMES="[]"
418+
ENV_FILE="wrangler.${{ inputs.github-environment }}.jsonc"
419+
if [ -n "${{ inputs.github-environment }}" ] && [ -f "$ENV_FILE" ]; then
420+
VAR_NAMES=$(ENV_FILE="$ENV_FILE" node --eval '
421+
const fs = require("fs");
422+
function stripJsonComments(str) {
423+
let result = "", inString = false, inLine = false, inBlock = false, i = 0;
424+
while (i < str.length) {
425+
if (!inLine && !inBlock && str[i] === "\"" && (i === 0 || str[i-1] !== "\\")) { inString = !inString; result += str[i]; i++; continue; }
426+
if (inString) { result += str[i]; i++; continue; }
427+
if (!inBlock && str.slice(i,i+2) === "//") { inLine = true; i += 2; continue; }
428+
if (!inLine && str.slice(i,i+2) === "/*") { inBlock = true; i += 2; continue; }
429+
if (inBlock && str.slice(i,i+2) === "*/") { inBlock = false; i += 2; continue; }
430+
if (inLine && (str[i] === "\n" || str[i] === "\r")) { inLine = false; result += str[i]; i++; continue; }
431+
if (inLine || inBlock) { i++; continue; }
432+
result += str[i]; i++;
433+
}
434+
return result;
435+
}
436+
const cfg = JSON.parse(stripJsonComments(fs.readFileSync(process.env.ENV_FILE, "utf8")));
437+
console.log(JSON.stringify(Object.keys(cfg.vars || {})));
438+
')
439+
fi
440+
441+
# Filter out secrets that conflict with vars
442+
FILTERED=$(echo "$SECRETS_JSON" | VAR_NAMES="$VAR_NAMES" node --eval '
443+
const secrets = JSON.parse(require("fs").readFileSync("/dev/stdin", "utf8"));
444+
const varNames = new Set(JSON.parse(process.env.VAR_NAMES));
445+
const filtered = {};
446+
for (const [k, v] of Object.entries(secrets)) {
447+
if (varNames.has(k)) {
448+
console.error(`Skipping secret "${k}" - already defined as a var in wrangler config`);
449+
} else {
450+
filtered[k] = v;
451+
}
452+
}
453+
console.log(JSON.stringify(filtered));
454+
')
455+
456+
if [ "$FILTERED" == "{}" ]; then
457+
echo "No secrets to upload (all filtered as var conflicts)"
458+
exit 0
459+
fi
460+
461+
echo "$FILTERED" > /tmp/worker-secrets.json
462+
npx wrangler secret bulk /tmp/worker-secrets.json --name "${{ inputs.worker-name }}"
463+
rm -f /tmp/worker-secrets.json

0 commit comments

Comments
 (0)