diff --git a/baker/liveCommit.ts b/baker/liveCommit.ts index 85e084408b2..f9c2cfd7eab 100644 --- a/baker/liveCommit.ts +++ b/baker/liveCommit.ts @@ -1,160 +1,126 @@ -import { keyBy, mapValues, sortBy, memoize } from "lodash" -import parseArgs from "minimist" -import opener from "opener" import { execWrapper } from "../db/execWrapper.js" -import { DeployTarget, ProdTarget } from "./DeployTarget.js" import { dayjs } from "@ourworldindata/utils" +import yargs from "yargs" +import { hideBin } from "yargs/helpers" /** * Retrieves information about the deployed commit on a live or staging server. * Usage examples: - * - `yarn fetchServerStatus` will retrieve information about the deployed commits for _all_ servers, and show a table - * - `yarn fetchServerStatus live` will retrieve the commit that's live on https://ourworldindata.org and opens it in GitHub - * That's equivalent to `yarn fetchServerStatus live --open` - * - `yarn fetchServerStatus staging --show` will `git show` information about the commit deployed on https://staging-owid.netlify.app - * - `yarn fetchServerStatus --show --tree` will both show a git tree and a `git show` of the deployed commits on https://ourworldindata.org + * - `yarn fetchServerStatus` will retrieve information about the currently deployed commit on https://ourworldindata.org and show it in a table + * - `yarn fetchServerStatus new-feature-branch` will retrieve the commit that's current on http://staging-site-new-feature-branch + * (same as `yarn fetchServerStatus staging-site-new-feature-branch` or `yarn fetchServerStatus http://staging-site-new-feature-branch`) + * - Other options are `--table`, `--show`, `--tree` to show the commit info in a table, `git show`, and `git log --graph`, respectively. * * Note: * For the local git commands to work you need to have that commit on your machine. Run a `git fetch` if you're getting a git error message. - * If it still doesn't work, the live commit is not pushed to GitHub yet. That should only happen on a staging server, never on live. */ -const servers = Object.values(DeployTarget) +interface CmdOptions { + server: string + tree: boolean + table: boolean + show: boolean +} + +const runCommand = async (options: CmdOptions) => { + const commitSha = await fetchCommitSha(options.server) + + if (options.table) { + const commitInfo = await fetchGithubCommitInfo(commitSha) + console.table({ + ...commitInfo, + commitDate: dayjs(commitInfo.commitDate).fromNow(), + commitUrl: `https://github.com/owid/owid-grapher/commit/${commitSha}`, + }) + } -const args = parseArgs(process.argv.slice(2)) + if (options.tree) { + await execWrapper( + `git log -10 --graph --oneline --decorate --color=always ${commitSha}` + ) + } + + if (options.show) { + await execWrapper(`git show --stat --color=always ${commitSha}`) + } +} -const showTree = args["tree"] -const showCommit = args["show"] -const openInBrowser = args["open"] || !(showCommit || showTree) +const getServerBaseUrl = (server: string) => { + if (server.startsWith("http")) return server -const getServerUrl = (server: string) => - server === ProdTarget - ? "https://ourworldindata.org" - : `https://${server}-owid.netlify.com` + if (server.startsWith("staging-site-")) return `http://${server}` + else return `http://staging-site-${server}` +} -const fetchCommitSha = async (server: string) => - fetch(`${getServerUrl(server)}/head.txt`) +const fetchCommitSha = async (server: string) => { + const headUrl = `${getServerBaseUrl(server)}/head.txt` + console.log("Fetching commit sha from", headUrl) + return fetch(headUrl) .then((res) => { if (res.ok) return res throw Error(`Request rejected with status ${res.status}`) }) - .then(async (resp) => ({ - commitSha: await resp.text(), + .then((resp) => resp.text()) + .then((sha) => sha.trim()) +} + +const fetchGithubCommitInfo = async ( + commitSha: string +): Promise => + await fetch( + `https://api.github.com/repos/owid/owid-grapher/git/commits/${commitSha}`, + { + headers: { + Accept: "application/vnd.github.v3", + }, + } + ) + .then((response) => response.json()) + .then((data) => ({ + commitSha: data.sha, + commitDate: dayjs(data.author.date).toDate(), + commitAuthor: data.author.name, + commitMessage: data.message, })) interface ServerCommitInformation { - serverName: string commitSha: string | undefined commitDate: Date | undefined commitAuthor: string | undefined commitMessage: string | undefined } -const fetchAll = async () => { - const commits = await Promise.all( - servers.map(async (serverName) => { - let commitInformation = undefined - try { - commitInformation = await fetchCommitSha(serverName) - } catch { - commitInformation = undefined - } - - return { - serverName, - ...commitInformation, - commitDate: undefined, - commitAuthor: undefined, - commitMessage: undefined, - } as ServerCommitInformation - }) - ) - - const _fetchGithubCommitInfo = async (commitSha: string) => - await fetch( - `https://api.github.com/repos/owid/owid-grapher/git/commits/${commitSha}`, - { - headers: { - Accept: "application/vnd.github.v3", - }, - } - ).then((response) => response.json()) - - // Memoize so as to not fetch information about the same commit twice - const fetchGithubCommitInfo = memoize(_fetchGithubCommitInfo) - - const commitsWithInformation = await Promise.all( - commits.map(async (commit) => { - if (!commit.commitSha) return commit - - const response = await fetchGithubCommitInfo(commit.commitSha) - - return { - ...commit, - commitSha: commit.commitSha.substring(0, 7), - commitDate: - response?.author?.date && new Date(response.author.date), - commitAuthor: response?.author?.name, - commitMessage: response?.message?.split("\n")?.[0], - } as ServerCommitInformation - }) +void yargs(hideBin(process.argv)) + .command( + "$0 [server]", + "Fetch info about deployed commit from live or staging server", + (yargs) => { + yargs + .positional("server", { + type: "string", + default: "https://ourworldindata.org", + describe: "Base URL of the site", + }) + .option("table", { + type: "boolean", + default: true, + description: "Show info in a table", + }) + .option("show", { + type: "boolean", + default: false, + description: "Show info in a 'git show''", + }) + .option("tree", { + type: "boolean", + default: false, + description: "Show info in a 'git tree'", + }) + }, + async (options) => { + await runCommand(options) + } ) - - return sortBy(commitsWithInformation, (c) => c.commitDate ?? 0).reverse() -} - -if (args._[0]) { - // fetch information for one specific server - const server = args._[0] - fetchCommitSha(server) - .then(async ({ commitSha }) => { - if (showTree) - await execWrapper( - `git log -10 --graph --oneline --decorate --color=always ${commitSha}` - ) - - if (showTree && showCommit) console.log() - - if (showCommit) - await execWrapper(`git show --stat --color=always ${commitSha}`) - - if (openInBrowser) - opener( - `https://github.com/owid/owid-grapher/commit/${commitSha}` - ) - }) - .catch((err) => - console.error( - `Could not retrieve commit information from ${getServerUrl( - server - )}. ${err}` - ) - ) -} else { - // fetch information for _all_ servers - void fetchAll().then((commitInformation) => { - const data = mapValues( - keyBy( - commitInformation, - (commitInformation) => commitInformation.serverName - ), - (commitInformation) => { - const { commitSha, commitDate, commitAuthor, commitMessage } = - commitInformation - - return { - commitSha, - commitDate: commitDate && dayjs(commitDate).fromNow(), - commitAuthor, - commitMessage: - // truncate to 50 characters - commitMessage && commitMessage.length > 50 - ? commitMessage?.substr(0, 50) + "…" - : commitMessage, - } - } - ) - - console.table(data) - }) -} + .help() + .alias("help", "h") + .strict().argv diff --git a/package.json b/package.json index 9e6b29f3f4c..fc29b66b5c8 100644 --- a/package.json +++ b/package.json @@ -231,7 +231,6 @@ "@types/ini": "^4", "@types/jest": "^29.5.5", "@types/js-yaml": "^4.0.5", - "@types/opener": "^1.4.0", "@types/topojson-server": "^3.0.1", "@typescript-eslint/eslint-plugin": "^7.2.0", "@typescript-eslint/parser": "^7.2.0", @@ -245,7 +244,6 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "lint-staged": "^15.2.2", - "opener": "^1.5.2", "sass": "^1.69.5", "tmex": "^1.0.8", "topojson-server": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 58c5f76ecd8..65ccf64a4db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5185,15 +5185,6 @@ __metadata: languageName: node linkType: hard -"@types/opener@npm:^1.4.0": - version: 1.4.0 - resolution: "@types/opener@npm:1.4.0" - dependencies: - "@types/node": "npm:*" - checksum: 10/b764cf208335e19c1e48d98feeb6c9183d6fd334b2c90386eca3015556b88f721427a5cbaa3a8e65de3d2c6c39c60487328d49940e59096c63d023d6ee3528bf - languageName: node - linkType: hard - "@types/papaparse@npm:^5.3.5": version: 5.3.5 resolution: "@types/papaparse@npm:5.3.5" @@ -11075,7 +11066,6 @@ __metadata: "@types/minimist": "npm:^1.2.2" "@types/mousetrap": "npm:^1.6.9" "@types/mysql": "npm:^2.15.21" - "@types/opener": "npm:^1.4.0" "@types/papaparse": "npm:^5.3.5" "@types/progress": "npm:^2.0.5" "@types/prompts": "npm:^2.0.14" @@ -11168,7 +11158,6 @@ __metadata: nodejs-polars: "npm:^0.7.2" normalize.css: "npm:^8.0.1" openai: "npm:^4.6.0" - opener: "npm:^1.5.2" p-map: "npm:^4.0.0" papaparse: "npm:^5.3.1" prettier: "npm:^3.2.5" @@ -15410,7 +15399,7 @@ __metadata: languageName: node linkType: hard -"opener@npm:^1.5.1, opener@npm:^1.5.2": +"opener@npm:^1.5.1": version: 1.5.2 resolution: "opener@npm:1.5.2" bin: