mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-14 02:50:51 +08:00
httpd: - Serve the API at /api, not only under /v1 - Keep serving it at /api/v1, without a redirect, until the first major release after explorer and the Open Graph worker switch to /api - Remove apiVersion: released explorers do not read it - Add `httpd.releases` to `/info`, set by the artifacts feature explorer: - Remove the API version check, its config and the unused compare-versions dependency - Keep the node version in a plain parse error message - Add `minimumSupportedVersion`, set to 0.28.0, and warn on nodes whose major is older, treating 0.y as the major before 1.0 - Do not warn on builds without a release number - Show a warning on the node page of an outdated node - Mark an outdated node in the seed picker on every page - Name the node version and the floor in parse errors - Drop the `/node` fallback for httpd without `/info`, which predates the floor - Check the status, not `ResponseError`, so the Open Graph worker can import compat without the fetcher - Name the httpd release each shim serves, not a date - Drop the mime shim for httpd 0.18.1 and the unused `lib/file.ts` - Read the node from `/info` in repo views - Pass the node and its features to repo views as one `node` param - Show the releases tab and pages when the node supports releases, and the counter only when there is a count - Read a release count as release support on older httpd - Test the flag and the fallback docs: - Restructure docs/api-changes.md: the supported versions, one table of removals, fixed fields per change, and a link to ADR 0001 for the rules - Say in ADR 0001 that each compat comment names what the other side does - Say in ADR 0001 when a capability needs a flag in /info tests: - Run e2e tests on httpd 0.30.0, above the floor, instead of 0.26.0 - Run the release tests on it too, so they cover the compat shims - Skip only those that need release counts per scope on it - Test a node without release support through a mocked `/info` flag, instead of an httpd that predates the floor
78 lines
2.3 KiB
TypeScript
78 lines
2.3 KiB
TypeScript
import type { Options } from "execa";
|
|
|
|
import { execa } from "execa";
|
|
import * as Crypto from "node:crypto";
|
|
import { fileURLToPath } from "node:url";
|
|
import * as Path from "node:path";
|
|
import * as Fs from "node:fs/promises";
|
|
|
|
// Generate string of 12 random characters with 8 bits of entropy.
|
|
export function randomTag(): string {
|
|
return Crypto.randomBytes(8).toString("hex");
|
|
}
|
|
|
|
export function createOptions(repoFolder: string, days: number): Options {
|
|
return {
|
|
cwd: repoFolder,
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
env: { RAD_LOCAL_TIME: (1671211684 + days * 86400).toString() },
|
|
};
|
|
}
|
|
|
|
const filename = fileURLToPath(import.meta.url);
|
|
export const supportDir = Path.dirname(filename);
|
|
export const tmpDir = Path.resolve(supportDir, "..", "./tmp");
|
|
export const fixturesDir = Path.resolve(supportDir, "..", "./fixtures");
|
|
const workspacePaths = [Path.join(tmpDir, "peers"), Path.join(tmpDir, "repos")];
|
|
|
|
export const heartwoodRelease = (
|
|
await Fs.readFile(`${supportDir}/heartwood-release`, "utf8")
|
|
).trim();
|
|
|
|
export const radicleHttpdRelease = (
|
|
await Fs.readFile(`${supportDir}/radicle-httpd-release`, "utf8")
|
|
).trim();
|
|
|
|
export const radicleArtifactRelease = (
|
|
await Fs.readFile(`${supportDir}/radicle-artifact-release`, "utf8")
|
|
).trim();
|
|
|
|
export const useLocalHttpd = process.env.USE_LOCAL_HTTPD === "true";
|
|
|
|
export const releaseCountsOnlyLocal =
|
|
"release counts per scope only exist in the local httpd build";
|
|
|
|
// Assert that binaries are installed and are the correct version.
|
|
export async function assertBinariesInstalled(
|
|
binary: string,
|
|
expectedVersion: string,
|
|
expectedPath: string,
|
|
): Promise<void> {
|
|
let which: string;
|
|
try {
|
|
({ stdout: which } = await execa("which", [binary]));
|
|
} catch {
|
|
throw new Error(`${binary} is not installed`);
|
|
}
|
|
if (Path.dirname(which) !== expectedPath) {
|
|
throw new Error(
|
|
`${binary} path doesn't match used ${binary} binary: ${expectedPath} !== ${which}`,
|
|
);
|
|
}
|
|
const { stdout: version } = await execa(binary, ["--version"]);
|
|
if (!version.includes(expectedVersion)) {
|
|
throw new Error(
|
|
`${binary} version ${version} does not satisfy ${expectedVersion}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
export async function removeWorkspace(): Promise<void> {
|
|
for (const path of workspacePaths) {
|
|
await Fs.rm(path, {
|
|
recursive: true,
|
|
force: true,
|
|
});
|
|
}
|
|
}
|