Skip to content

Content Diffing

If the automation involves pushing content to a remote destination — uploading, submitting, syncing, deploying — you may need to know what actually changed so you can skip what's already current.

Problem: You Don't Know What's Changed

The remote destination has no diff or versioning endpoint. You need to compare local and remote versions yourself.

Strategy: Download and Compare Directly

The simplest approach. Download the remote version and compare it to the local version byte-for-byte or field-by-field:

javascript
const remote = await downloadRemote(id);
const local = readFileSync(localPath);

if (Buffer.compare(remote, local) === 0) {
  console.log("Up to date, skipping");
} else {
  await upload(localPath);
}

Works well when content is small and cheap to download. Becomes slow if there are many items or large files.

Strategy: Hash Comparison

Compute a fingerprint of the content on both sides. Compare fingerprints instead of full content:

javascript
import { createHash } from "crypto";

function contentHash(buffer) {
  return createHash("sha256")
    .update(buffer)
    .digest("hex")
    .slice(0, 8);
}

const localHash = contentHash(readFileSync(localPath));
const remoteHash = contentHash(await downloadRemote(id));

if (localHash === remoteHash) {
  console.log("Up to date, skipping");
}

Faster than full comparison when you can compute the hash without downloading the entire file — for example, if the hash is stored as metadata.

Strategy: Embed a Version Marker

If you control the build or upload process, embed a version marker (hash, timestamp, version number) in the content itself. On subsequent runs, read just the marker from the remote side instead of downloading everything:

javascript
// During build: stamp the hash into the artifact
const hash = computeHash(sourceDir);
stampIntoArtifact(artifact, { content_hash: hash });

// During diff: read the marker from the remote version
const remoteHash = await readRemoteMarker(id);
if (remoteHash === localHash) {
  console.log("Up to date, skipping");
}

This is the fastest approach for repeated runs — reading a small marker is cheaper than downloading or hashing the full content.

Problem: Some Remote Content Doesn't Have a Marker

If version stamping was added after some content was already pushed, older versions won't have a marker.

Solution: treat missing markers as needing an update. A missing marker never matches a local value, so the content gets pushed with the marker. After one cycle, all versions have markers and comparison works normally.