Last active
August 25, 2023 08:18
-
-
Save ItsWendell/2f2694e28d405862916e24088ca74014 to your computer and use it in GitHub Desktop.
Expo: Runtime Versioning based on pnpm lock
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env -S pnpm tsx | |
import crypto from "crypto"; | |
import fs from "fs"; | |
import path from "path"; | |
import { | |
createFingerprintAsync, | |
diffFingerprintChangesAsync, | |
} from "@expo/fingerprint"; | |
const projectRoot = process.cwd(); | |
const hash = crypto.createHash("sha1"); | |
const run = async () => { | |
console.log( | |
"[Runtime Versioning] Checking runtime version in " + projectRoot, | |
); | |
const runtimeVersionPath = path.join(projectRoot, "runtime-version.json"); | |
const runtimeVersionJson = fs.readFileSync(runtimeVersionPath, "utf8"); | |
const runtimeVersion = JSON.parse(runtimeVersionJson); | |
const skipReasons = [ | |
// Skip the package.json scripts because they are not relevant to the runtime | |
"packageJson:scripts", | |
// WE don't consider the easBuild script relevant to the runtime | |
"easBuild", | |
] as const; | |
const fingerprint = await createFingerprintAsync(projectRoot, { | |
hashAlgorithm: "sha1", | |
}); | |
let sources = fingerprint.sources | |
// Filter out sources that we don't want to include in the hash | |
.filter((source) => { | |
if (!source.hash) { | |
return false; | |
} | |
return !skipReasons.some((reason) => source.reasons.includes(reason)); | |
}) | |
// Sort to make sure the order is consistent | |
.sort((a, b) => { | |
if (a.type !== b.type) { | |
return a.type > b.type ? 1 : -1; | |
} else if ("filePath" in a && "filePath" in b) { | |
return a.filePath.toLowerCase() > b.filePath.toLowerCase() ? 1 : -1; | |
} else if ("id" in a && "id" in b) { | |
return a.id > b.id ? 1 : -1; | |
} else { | |
return 0; | |
} | |
}); | |
for (const source of sources) { | |
if (!source.hash) { | |
throw new Error(`Source has no hash`); | |
} | |
// Push the hash of each source into the hash of the runtime version | |
await hash.update(source.hash); | |
} | |
const isCi = process.env.CI === "true"; | |
const hashHex = hash.digest("hex"); | |
if (runtimeVersion.hash !== hashHex) { | |
if (isCi) { | |
console.error( | |
"[Runtime Versioning] Runtime version is out of date, and won't be updated in CI", | |
); | |
process.exitCode = 1; | |
return; | |
} | |
const newFile = { | |
version: runtimeVersion.version + 1, | |
hash: hashHex, | |
sources, | |
}; | |
fs.writeFileSync(runtimeVersionPath, JSON.stringify(newFile, null, 2)); | |
console.log( | |
`[Runtime Versioning] Runtime version incremented to ${runtimeVersion.version}`, | |
); | |
} else { | |
console.log(`[Runtime Versioning] Runtime version is up to date`); | |
} | |
}; | |
run().catch((error) => { | |
console.error(error); | |
process.exitCode = 1; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment