Skip to content

Commit

Permalink
refactor(scripts): modernize fetchServerStatus script
Browse files Browse the repository at this point in the history
- get rid of Netlify staging server info
- only ever get info about one server
- remove `--open`
- better cli interface
  • Loading branch information
marcelgerber committed May 16, 2024
1 parent e24de9c commit b2b9fa0
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 145 deletions.
228 changes: 97 additions & 131 deletions baker/liveCommit.ts
Original file line number Diff line number Diff line change
@@ -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<ServerCommitInformation> =>
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<CmdOptions>(
"$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
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down
13 changes: 1 addition & 12 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit b2b9fa0

Please sign in to comment.