Skip to content

Commit

Permalink
cta: env metadata with git
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Razon committed Aug 6, 2023
1 parent 1312f13 commit 6504c2c
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 6 deletions.
5 changes: 5 additions & 0 deletions packages/compose-tunnel-agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ const machineStatusCommand = process.env.MACHINE_STATUS_COMMAND
? JSON.parse(process.env.MACHINE_STATUS_COMMAND) as MachineStatusCommand
: undefined

const envMetadata = process.env.ENV_METADATA
? JSON.parse(process.env.ENV_METADATA) as Record<string, unknown>
: undefined

const log = pino({
level: process.env.DEBUG || process.env.DOCKER_PROXY_DEBUG ? 'debug' : 'info',
}, pinoPretty({ destination: pino.destination(process.stderr) }))
Expand Down Expand Up @@ -139,6 +143,7 @@ const main = async () => {
machineStatus: machineStatusCommand
? async () => await runMachineStatusCommand({ log, docker })(machineStatusCommand)
: undefined,
envMetadata,
}),
dockerProxyHandlers: createDockerProxyHandlers({
log: log.child({ name: 'docker-proxy' }),
Expand Down
9 changes: 8 additions & 1 deletion packages/compose-tunnel-agent/src/http/api-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { Logger } from '@preevy/common'
import { SshState } from '../ssh'
import { NotFoundError, respondAccordingToAccept, respondJson, tryHandler } from './http-server-helpers'

const createApiServerHandler = ({ log, currentSshState, machineStatus }: {
const createApiServerHandler = ({ log, currentSshState, machineStatus, envMetadata }: {
log: Logger
currentSshState: () => Promise<SshState>
machineStatus?: () => Promise<{ data: Buffer; contentType: string }>
envMetadata?: Record<string, unknown>
}) => tryHandler({ log }, async (req, res) => {
const { pathname: path } = url.parse(req.url || '')

Expand All @@ -27,6 +28,12 @@ const createApiServerHandler = ({ log, currentSshState, machineStatus }: {
return
}

if (req.method === 'GET' && path === '/metadata' && envMetadata) {
res.setHeader('Content-Type', 'application/json')
res.end(JSON.stringify(envMetadata))
return
}

throw new NotFoundError()
})

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/ci-providers/azure-pipelines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const azurePipelinesCiProvider = (): CiProvider => ({
telemetryId: 'azurepipelines',
currentlyRunningInProvider: () => Boolean(process.env.BUILD_DEFINITIONNAME),
branchName: () => process.env.BUILD_SOURCEBRANCHNAME,
gitCommit: () => process.env.BUILD_SOURCEVERSION as string,
pullRequestNumber: () => stringOrUndefinedToNumber(
process.env.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER || process.env.SYSTEM_PULLREQUEST_PULLREQUESTID,
),
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/ci-providers/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export type CiProvider = {
telemetryId: string
currentlyRunningInProvider: () => boolean
branchName: () => string | undefined
gitCommit: () => string
pullRequestNumber: () => number | undefined
repoUrl: () => string | undefined
}
1 change: 1 addition & 0 deletions packages/core/src/ci-providers/circle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const circleCiProvider = (): CiProvider => ({
telemetryId: 'circle',
currentlyRunningInProvider: () => Boolean(process.env.CI === 'true' && process.env.CIRCLECI === 'true'),
branchName: () => process.env.CIRCLE_BRANCH,
gitCommit: () => process.env.CIRCLE_SHA1 as string,
pullRequestNumber: () => stringOrUndefinedToNumber(process.env.CIRCLE_PR_NUMBER)
|| extractPrNumberFromUrlPath(process.env.CIRCLE_PULL_REQUEST),
repoUrl: () => process.env.CIRCLE_REPOSITORY_URL,
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/ci-providers/github-actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import fs from 'fs'
import { CiProvider } from './base'
import { stringOrUndefinedToNumber } from './common'

const readEventPayload = () => (
process.env.GITHUB_EVENT_PATH
? JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, { encoding: 'utf8' }))
: undefined
)

// https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
export const githubActionsCiProvider = (): CiProvider => ({
name: 'GitHub Actions',
Expand All @@ -10,6 +17,7 @@ export const githubActionsCiProvider = (): CiProvider => ({
pullRequestNumber: () => stringOrUndefinedToNumber(
process.env.GITHUB_REF?.match(/^refs\/pull\/(\d+)/)?.[1],
),
gitCommit: () => readEventPayload()?.pull_request?.head?.sha ?? process.env.GITHUB_SHA as string,
repoUrl: () => (
(process.env.GITHUB_REPOSITORY && process.env.GITHUB_SERVER_URL)
? `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}.git`
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/ci-providers/gitlab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const gitlabActionsCiProvider = (): CiProvider => ({
branchName: () => process.env.CI_COMMIT_BRANCH
|| process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|| process.env.CI_COMMIT_REF_NAME,
gitCommit: () => process.env.CI_COMMIT_SHA as string,
pullRequestNumber: () => stringOrUndefinedToNumber(
process.env.CI_MERGE_REQUEST_IID || process.env.CI_EXTERNAL_PULL_REQUEST_IID
),
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/ci-providers/travis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const travisCiProvider = (): CiProvider => ({
telemetryId: 'travis',
currentlyRunningInProvider: () => Boolean(process.env.CI && process.env.TRAVIS),
branchName: () => (process.env.TRAVIS_TAG ? undefined : process.env.TRAVIS_BRANCH),
gitCommit: () => process.env.TRAVIS_COMMIT as string,
pullRequestNumber: () => (process.env.TRAVIS_PULL_REQUEST && process.env.TRAVIS_PULL_REQUEST !== 'false'
? nanToUndefined(Number(process.env.TRAVIS_PULL_REQUEST))
: undefined),
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/commands/up/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { remoteProjectDir } from '../../remote-files'
import { Logger } from '../../log'
import { tunnelUrlsForEnv } from '../../tunneling'
import { FileToCopy, uploadWithSpinner } from '../../upload-files'
import { detectEnvMetadata } from '../../env-metadata'

const createCopiedFileInDataDir = (
{ projectLocalDataDir, filesToCopy } : {
Expand Down Expand Up @@ -157,6 +158,7 @@ const up = async ({
knownServerPublicKeyPath: path.join(remoteDir, knownServerPublicKey.remote),
user,
machineStatusCommand: await machineDriver.machineStatusCommand(machine),
envMetadata: await detectEnvMetadata(),
}, fixedModel)

const modelStr = yaml.stringify(remoteModel)
Expand Down
17 changes: 13 additions & 4 deletions packages/core/src/compose-tunnel-agent-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,17 @@ export const addBaseComposeTunnelAgentService = (
})

export const addComposeTunnelAgentService = (
{ tunnelOpts, sshPrivateKeyPath, knownServerPublicKeyPath, urlSuffix, debug, user, envId, machineStatusCommand }: {
{
tunnelOpts,
sshPrivateKeyPath,
knownServerPublicKeyPath,
urlSuffix,
debug,
user,
envId,
machineStatusCommand,
envMetadata,
}: {
tunnelOpts: TunnelOpts
urlSuffix: string
sshPrivateKeyPath: string
Expand All @@ -49,6 +59,7 @@ export const addComposeTunnelAgentService = (
user: string
envId: string
machineStatusCommand?: MachineStatusCommand
envMetadata?: Record<string, unknown>
},
model: ComposeModel,
): ComposeModel => ({
Expand All @@ -67,9 +78,6 @@ export const addComposeTunnelAgentService = (
protocol: 'tcp',
},
],
// extra_hosts: [
// 'host.docker.internal:host-gateway',
// ],
volumes: [
{
type: 'bind',
Expand Down Expand Up @@ -99,6 +107,7 @@ export const addComposeTunnelAgentService = (
PREEVY_ENV_ID: envId,
PORT: COMPOSE_TUNNEL_AGENT_PORT.toString(),
...machineStatusCommand ? { MACHINE_STATUS_COMMAND: JSON.stringify(machineStatusCommand) } : {},
...envMetadata ? { ENV_METADATA: JSON.stringify(envMetadata) } : {},
...debug ? { DEBUG: '1' } : {},
HOME: '/preevy',
},
Expand Down
37 changes: 37 additions & 0 deletions packages/core/src/env-metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as git from './git'
import { detectCiProvider } from './ci-providers'

export type GitAuthor = { name: string; email: string }

export type GitMetadata = {
branch?: string
commit: string
author: GitAuthor
repoUrl?: string
pullRequestNumber?: number
}

export type EnvMetadata = {
git?: GitMetadata
}

const detectGitMetadata = async (): Promise<GitMetadata | undefined> => {
const ciProvider = detectCiProvider()
const branch = await git.gitBranchName()
if (!branch) {
return undefined
}
const commit = ciProvider?.gitCommit() ?? await git.gitCommit() as string

return {
branch: ciProvider?.branchName() ?? branch,
commit,
author: await git.gitAuthor(commit) as GitAuthor,
pullRequestNumber: ciProvider?.pullRequestNumber(),
repoUrl: ciProvider?.repoUrl() || await git.gitRemoteTrackingBranchUrl(),
}
}

export const detectEnvMetadata = async (): Promise<EnvMetadata> => ({
git: await detectGitMetadata(),
})
13 changes: 12 additions & 1 deletion packages/core/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@ import { execPromiseStdout } from './child-process'
export const gitBranchName = async () => await execPromiseStdout('git rev-parse --abbrev-ref HEAD')
.catch(() => undefined)

export const gitCommit = async () => await execPromiseStdout('git rev-parse HEAD')
.catch(() => undefined)

export const gitAuthor = async (commit?: string) => {
const [email, name] = await Promise.all([
`git log -1 ${commit} --pretty=format:'%ae'`,
`git log -1 ${commit} --pretty=format:'%an'`,
].map(cmd => execPromiseStdout(cmd).catch(() => undefined)))
return email === undefined || name === undefined ? undefined : { name, email }
}

export const gitRemoteTrackingBranchUrl = async (localBranch?: string) => {
const b = localBranch ?? await execPromiseStdout('git rev-parse --name-only HEAD')
const b = localBranch ?? (await execPromiseStdout('git rev-parse --abbrev-ref HEAD'))
const trackingRemote = await execPromiseStdout(`git config branch.${b}.remote`)
return await execPromiseStdout(`git config remote.${trackingRemote}.url`)
}

0 comments on commit 6504c2c

Please sign in to comment.