Automation Health Checks: A Green Job Is Not a Publication Receipt
A publishing workflow can finish with a successful exit code after making no public post. That is sometimes correct: the queue may be empty, a seasonal trigger may be irrelevant, or every candidate may already exist on the destination account. The operational problem appears when the dashboard presents all of these outcomes as published.
This guide describes a reporting contract for a small publishing worker. It follows the data from selection through the remote write and into the final summary. The examples are illustrative application code; they do not depend on a particular platform API.
Define an outcome for each delivery
Separate the state of the job from the state of the delivery. A job can complete normally with a skipped delivery. It can also fail after the remote service created the post but before the local database recorded the result.
Useful delivery outcomes are published, skipped, rejected and uncertain. Include a reason for skipped or rejected items. For a published delivery, require an external identifier and retain the public URL when the platform supplies one.
Do not use a single boolean named success to represent all of these facts. That makes every downstream dashboard reconstruct information that the worker already knew.
Return structured results from helpers
A fallback publisher is a common source of misleading counts. The parent worker sees an empty queue, calls a helper that publishes a reviewed reserve post, then returns its original counter of zero. The helper performed the work, but the parent never collected the outcome.
Prefer a structured return value when both components are in the same process:
async function processQueue(queue, reserve) {
const item = await queue.nextApproved();
if (item) return publishReviewed(item);
return reserve.publishNextReviewed();
}
Both paths should produce the same result shape. If the helper is a separate process, establish a machine-readable output contract. Keep diagnostic messages on a separate stream, or use a clearly identified result record. Parsing a human log phrase can be a temporary compatibility repair, but changing the phrase would then risk breaking the counter.
Preserve evidence before counting
A published count should be backed by a response you can reconcile. For example:
{
"outcome": "published",
"contentId": "reviewed-item-42",
"externalId": "remote-record-123",
"publicUrl": "https://example.test/posts/remote-record-123"
}
The URL is illustrative. In a real adapter, use the service response or a verified lookup. Do not invent a URL format just to make the report look complete.
A missing URL does not necessarily mean the write failed. Preserve the external ID and report that public-link verification remains unavailable. A missing external ID after an ambiguous response needs an uncertain outcome and reconciliation before another write.
Track content supply as a separate dependency
An empty reviewed queue can stop publishing even when credentials, scheduling and API calls work correctly. Measure the number of unpublished, editorially approved candidates, rather than counting all files in a content directory.
A directory containing 40 drafts and one already-published article has no usable reserve. The file count alone conceals the problem. Count only items that satisfy the current eligibility rules and are absent from verified remote history.
Set an alert threshold appropriate to the publishing cadence. Replenishment still requires writing and review; changing a status field on an unfinished draft does not create usable content.
Keep dry runs observably read only
A dry run should authenticate, read history and identify a candidate without claiming or publishing it. Be careful with shared setup code: token persistence or queue mutation can happen before the code reaches the branch labelled dry run.
Test the boundary by replacing the network adapter with a recording fake. Run the diagnostic path and assert that no publication or claim request occurred. Checking the final exit code is insufficient.
A useful dry-run summary states the account, candidate identity, remaining reviewed reserve and the fact that no public write was attempted. Credentials must never appear in that summary.
Test the report against the side effects
For each test scenario, compare reported counts with recorded remote writes. Include an empty queue with a usable reserve, an exhausted reserve, a rejected request and a write followed by a failed local confirmation.
The helper case is particularly important. If the helper creates one post, the parent summary must acknowledge that publication. Conversely, an authentication check that succeeds must not increment the published count.
Finally, inspect the actual remote record during operational validation. Tests establish the application's contract; the destination account provides evidence that the live publication exists.
With these distinctions, the dashboard becomes useful for diagnosis. It can show that the scheduler ran, the account authenticated, the reserve was empty, or a particular post was published. Those are separate facts, and keeping them separate makes each repair much more precise.
Top comments (0)