Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .actor/actor.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@
"name": "webhook-debugger-logger",
"title": "Webhook Debugger, Logger & API Mocking Suite",
"description": "Enterprise-grade tool to test, debug, and mock webhooks. Features real-time SSE streaming, request replay, HTTP forwarding, and JSON schema validation. Perfect for Stripe, GitHub, and Shopify integrations.",
"version": "3.0.1",
"version": "3.0.2",
"output": "./output_schema.json",
"input": "./input_schema.json",
"webServerSchema": "./web_server_schema.json",
"usesStandbyMode": true,
"dockerfile": "../Dockerfile",
"categories": [
"DEVELOPER_TOOLS",
"UTILITIES",
"INTEGRATION_TOOLS"
],
"categories": ["DEVELOPER_TOOLS", "UTILITIES", "INTEGRATION_TOOLS"],
"homepageUrl": "https://apify.com/ar27111994/webhook-debugger-logger",
"storages": {
"dataset": "./dataset_schema.json",
Expand Down
14 changes: 8 additions & 6 deletions .actor/input_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,19 @@
"example": "my-secret-key-123",
"editor": "textfield"
},
"allowedIps": {
"type": "array",
"title": "IP Whitelist (CIDR)",
"description": "Only accept traffic from these specific IPs or CIDR blocks. Leave blank for public access.",
"editor": "stringList"
},
"signatureVerificationSecret": {
"type": "string",
"title": "Webhook Signing Secret",
"description": "Signing secret used by the webhook provider selected in the 'Webhook Signature Verification' settings below.",
"isSecret": true,
"editor": "textfield"
},
"allowedIps": {
"type": "array",
"title": "IP Whitelist (CIDR)",
"description": "Only accept traffic from these specific IPs or CIDR blocks. Leave blank for public access.",
"editor": "stringList"
},
"signatureVerification": {
"type": "object",
"title": "Webhook Signature Verification",
Expand Down Expand Up @@ -215,6 +215,7 @@
"slack": {
"type": "object",
"title": "Slack",
"description": "Slack alert channel settings for webhook notifications.",
"properties": {
"webhookUrl": {
"type": "string",
Expand All @@ -227,6 +228,7 @@
"discord": {
"type": "object",
"title": "Discord",
"description": "Discord alert channel settings for webhook notifications.",
"properties": {
"webhookUrl": {
"type": "string",
Expand Down
4 changes: 2 additions & 2 deletions .actor/web_server_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"info": {
"title": "Webhook Debugger & Logger API",
"description": "OpenAPI description for the Webhook Debugger & Logger Actor web server. Authentication is configuration-driven: when authKey is configured, management routes require either a bearer token or the key query parameter; when authKey is unset, those routes remain accessible without credentials.",
"version": "3.0.1"
"version": "3.0.2"
},
"servers": [
{
Expand Down Expand Up @@ -80,7 +80,7 @@
"schema": {
"type": "string"
},
"example": "Webhook Debugger & Logger (v3.0.1)\nActive Webhooks: 1\nSignature Verification: STRIPE"
"example": "Webhook Debugger & Logger (v3.0.2)\nActive Webhooks: 1\nSignature Verification: STRIPE"
}
}
},
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ jobs:
- name: Lint
run: npm run lint

- name: Validate Web Server Schema
run: npm run validate:web-server-schema
- name: Validate Actor Schemas
run: npm run validate:schemas

- name: Type Check
run: npm run typecheck
Expand Down
27 changes: 24 additions & 3 deletions .github/workflows/link-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,28 @@ jobs:
node - <<'EOF'
const fs = require('node:fs');

const normalizeUrlKey = (value) => {
if (typeof value !== 'string' || value.length === 0) {
return null;
}

try {
const { origin, pathname } = new URL(value);
return `${origin}${pathname}`;
} catch {
return null;
}
};

const results = JSON.parse(fs.readFileSync('lychee/results.json', 'utf8'));
const softHandledUrls = new Set([
const softHandledUrls = [
'https://www.npmjs.com/package/webhook-debugger-logger',
'https://www.npmjs.com/package/isolated-vm?activeTab=readme',
'https://img.shields.io/coderabbit/prs/github/ar27111994/webhook-debugger-logger?utm_source=oss&utm_medium=github&utm_campaign=ar27111994%2Fwebhook-debugger-logger&labelColor=171717&color=FF570A&link=https%3A%2F%2Fcoderabbit.ai&label=CodeRabbit+Reviews',
]);
];
const softHandledUrlKeys = new Set(
softHandledUrls.map((value) => normalizeUrlKey(value)).filter(Boolean),
);

const softFailures = [];
const hardFailures = [];
Expand All @@ -110,8 +126,13 @@ jobs:
for (const failure of failures) {
const url = failure.url;
const code = failure.status?.code;
const normalizedUrl = normalizeUrlKey(url);

if (softHandledUrls.has(url) && (code === 403 || code === 408 || code === 429)) {
if (
normalizedUrl
&& softHandledUrlKeys.has(normalizedUrl)
&& (code === 403 || code === 408 || code === 429)
) {
softFailures.push({ source, url, code, text: failure.status?.text ?? '' });
continue;
}
Expand Down
12 changes: 7 additions & 5 deletions .github/workflows/release-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,18 @@ jobs:
run: |
owner="${GITHUB_REPOSITORY_OWNER,,}"
release_tag="${RELEASE_TAG:-pr-${{ github.event.pull_request.number || github.run_number }}}"
version="${release_tag#v}"
minor="$(echo "${version}" | cut -d. -f1,2)"
image_name="webhook-debugger-logger"

{
echo "tags<<EOF"
echo "ghcr.io/${owner}/${image_name}:${release_tag}"
echo "ghcr.io/${owner}/${image_name}:${version}"
echo "ghcr.io/${owner}/${image_name}:${minor}"
if [[ "${RELEASE_PRERELEASE}" != "true" ]]; then
if [[ "${GITHUB_EVENT_NAME}" == 'release' ]]; then
version="${release_tag#v}"
minor="$(echo "${version}" | cut -d. -f1,2)"
echo "ghcr.io/${owner}/${image_name}:${version}"
echo "ghcr.io/${owner}/${image_name}:${minor}"
fi
if [[ "${GITHUB_EVENT_NAME}" == 'release' && "${RELEASE_PRERELEASE}" != 'true' ]]; then
echo "ghcr.io/${owner}/${image_name}:latest"
fi
echo "EOF"
Expand Down
32 changes: 25 additions & 7 deletions .github/workflows/release-npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ on:
branches: [main]

jobs:
publish:
validate:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # Required for provenance (used in package.json) (optional but good practice)
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -25,22 +24,41 @@ jobs:
- name: Install Dependencies
run: npm ci --legacy-peer-deps

- name: Validate Web Server Schema
run: npm run validate:web-server-schema
- name: Validate Actor Schemas
run: npm run validate:schemas

- name: Verify Builds/Tests
run: npm run test:jest -- --detectOpenHandles --forceExit

- name: Skip publish outside release events
- name: Confirm publish is deferred outside release events
if: github.event_name != 'release'
run: echo "PR validation complete; npm publish only runs for published releases."
run: echo "Validation complete; npm publishing only runs in the release-only publish job."

publish:
if: github.event_name == 'release'
needs: validate
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # Required for npm provenance on published releases.
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"

- name: Install Dependencies
run: npm ci --legacy-peer-deps

# unset NODE_AUTH_TOKEN because it's automatically set by the setup-node action
# node@v24.0.0+
# https://github.com/orgs/community/discussions/176761
# https://github.com/actions/setup-node/issues/1440#issuecomment-3705123143
- name: Publish to NPM
if: github.event_name == 'release'
run: |
unset NODE_AUTH_TOKEN
npm publish
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file.

## [3.0.2] - 2026-04-17

### Fixed (3.0.2)

- **Apify**: Restore valid Actor input schema metadata by adding the missing nested alert channel descriptions required by Apify schema validation.
- **Apify**: Reorder `signatureVerificationSecret` so it appears directly above `signatureVerification` in the Actor input UI while preserving the same backward-compatible runtime mapping.
- **CI/CD**: Validate the Actor input schema with `apify validate-schema` alongside the web server schema so Apify build-time schema errors are caught before release.
- **CI/CD**: Split npm validation from npm publishing so `id-token: write` is granted only during release publishing, and keep Docker PR validation tags limited to the single synthetic PR tag.
- **CI/CD**: Normalize known flaky external link handling in the link check workflow by matching stable URL origin-and-path keys instead of full query-string URLs.
- **Tooling**: Stop hardcoding the Apify CLI package version inside the validation script by invoking the project-installed `apify` binary instead.
- **Tooling**: Add `@apify/input_secrets` as an explicit development dependency and align sync-version test fixtures with the production HTTP status key style.

## [3.0.1] - 2026-04-15

### Fixed (3.0.1)
Expand All @@ -10,6 +22,8 @@ All notable changes to this project will be documented in this file.
- **CI/CD**: Make the release-only npm and Docker workflows report successful pull request checks without publishing artifacts, so Dependabot PRs do not remain stuck waiting on required checks.
- **CI/CD**: Make the required `Link Check` workflow run on every pull request so dependency-only PRs no longer remain stuck in an expected state when path filters skip the job.
- **Apify**: Move the webhook signing secret to a top-level `signatureVerificationSecret` input with `isSecret: true`, while keeping runtime compatibility with older nested secret values.
- **Forwarding**: Implement strict Content-Length parsing and enhance fallback logic in ForwardingService.
- **GitHub/NPM**: Update CI/CD, `package.json` and `package-lock.json` to use the latest versions of various dependencies.

## [3.0.0] - 2026-04-02

Expand Down
Loading
Loading