Line

You are reading the unreleased docs (next). See latest (v0.9)

ui/server/src/cloneJobs-1

Cockpit server, next. Source: n/a.

Variables#

CLONE_STAMP#

const CLONE_STAMP: "construct-cloned.json" = 'construct-cloned.json'

Defined in: ui/server/src/cloneJobs.mjs:203

Proof, inside the clone's own metadata directory, that THIS Cockpit made it ("Pull latest" touches only these).


DEFAULT_MAX_BYTES#

const DEFAULT_MAX_BYTES: number

Defined in: ui/server/src/cloneJobs.mjs:30


DEFAULT_TIMEOUT_MS#

const DEFAULT_TIMEOUT_MS: number

Defined in: ui/server/src/cloneJobs.mjs:31


LOGIN_HOSTS#

const LOGIN_HOSTS: readonly string[]

Defined in: ui/server/src/cloneJobs.mjs:33

: the only hosts the person's GitHub login (repoConnection.mjs) may be sent to, whatever CONSTRUCT_CLONE_HOSTS allows.


MARKER_PREFIX#

const MARKER_PREFIX: ".construct-clone-" = '.construct-clone-'

Defined in: ui/server/src/cloneJobs.mjs:139


UNSAFE_PULL_CONFIG#

const UNSAFE_PULL_CONFIG: readonly string[]

Defined in: ui/server/src/cloneJobs.mjs:42

review: .git/config settings that would send "Pull latest", or the credential fed to it, somewhere other than the recorded origin (url.*.insteadOf re-routes the fetch AND the askpass answer; http.*, remote.*.proxy and credential.* change where and how it is sent; include.* pulls in a file that could set any of them) or run a program of the repository's choosing. Anything running inside a cloned project (its dev server, its scripts) can write that file, and comparing the origin URL alone does not see these. A pull is refused while any is set, before a token is fetched. Matched as section.name (git lower-cases both; * is any subsection or any name).

Functions#

cloneArgs()#

cloneArgs(__namedParameters): any[]

Defined in: ui/server/src/cloneJobs.mjs:113

The exact argv handed to git (after the git program name). Exported so a test can assert every flag.

Parameters#

__namedParameters
allowLocal?

boolean = false

branch?

any = null

depth?

any = null

dest

any

parsed

any

pin?

any = null

Returns#

any[]


cloneEnv()#

cloneEnv(__namedParameters?): object

Defined in: ui/server/src/cloneJobs.mjs:96

The environment git runs in: nothing inherited but PATH, and no config file, proxy, askpass or helper.

Parameters#

__namedParameters?
allowLocal?

boolean = false

askpass?

any = null

base?

any = process.env

Returns#

object

GIT_ALLOW_PROTOCOL

GIT_ALLOW_PROTOCOL: string

GIT_ASKPASS

GIT_ASKPASS: any

GIT_CONFIG_GLOBAL

GIT_CONFIG_GLOBAL: string = '/dev/null'

GIT_CONFIG_NOSYSTEM

GIT_CONFIG_NOSYSTEM: string = '1'

GIT_PROTOCOL_FROM_USER

GIT_PROTOCOL_FROM_USER: string = '0'

GIT_TERMINAL_PROMPT

GIT_TERMINAL_PROMPT: string = '0'

HOME

HOME: string = '/nonexistent'

LANG

LANG: string = 'C'

LC_ALL

LC_ALL: string = 'C'

PATH

PATH: any


createCloneJobs()#

createCloneJobs(deps?): object

Defined in: ui/server/src/cloneJobs.mjs:241

Parameters#

deps?
getRoot

() => string

Returns#

gitStatus

gitStatus: () => { cloneEnabled: boolean; code: string; minimum: string; ok: boolean; reason: any; version: any; } | { cloneEnabled: boolean; code: string; minimum: string; ok: boolean; reason: string; version: any; } | { cloneEnabled: boolean; code?: undefined; minimum: string; ok: boolean; reason?: undefined; version: any; }

: whether clone may run on this machine's git. Below 2.37.0 git silently ignores http.curloptResolve, the pin that keeps git on the addresses that were just checked to be public, so the anti-rebinding half of the SSRF defence would be off without a word. Refused rather than degraded: a clone with half its defence is not one we want to run. -> {ok, version, minimum, cloneEnabled, reason?, code?}

Returns

{ cloneEnabled: boolean; code: string; minimum: string; ok: boolean; reason: any; version: any; } | { cloneEnabled: boolean; code: string; minimum: string; ok: boolean; reason: string; version: any; } | { cloneEnabled: boolean; code?: undefined; minimum: string; ok: boolean; reason?: undefined; version: any; }

list

list: () => object[]

Returns

object[]

live

live: () => number

Test seam: resolves when the given job has finished.

Returns

number

cancel()

cancel(id): { body: { error: string; job?: undefined; ok: boolean; }; status: number; } | { body: { error: string; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; }; status: number; } | { body: { error?: undefined; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; }; status: number; }

-> {status, body}

Parameters
id

any

Returns

{ body: { error: string; job?: undefined; ok: boolean; }; status: number; } | { body: { error: string; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; }; status: number; } | { body: { error?: undefined; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; }; status: number; }

get()

get(id): object

Parameters
id

any

Returns

object

branch?

optional branch?: any = j.branch

bytes

bytes: any = j.bytes

code?

optional code?: any = j.errorCode

dir?

optional dir?: any = j.dest

error?

optional error?: any = j.error

finishedAt

finishedAt: any = j.finishedAt

id

id: any = j.id

kind

kind: string = 'clone'

log

log: any

name

name: any = j.slug

private

private: boolean

progress

progress: any = j.progress

startedAt

startedAt: any = j.startedAt

state

state: any = j.state

title

title: string

url

url: any = j.url

via?

optional via?: string = 'login'

pull()

pull(opts?): Promise<any>

"Pull latest" for a clone this Cockpit made: git pull --ff-only, argv only, contained, with the same one-time token handling as start(). -> {ok:true, name, upToDate, message, detail} | {ok:false, status, code, error}

Parameters
opts?
Returns

Promise<any>

recoverInterrupted()

recoverInterrupted(): object

: sweep the workspace for markers left by a server that is gone (called at server start, and usable any time). Removes only directories that carry OUR marker, are real directories, and sit directly under the workspace root; stops an orphaned git first when it is still running. A marker whose server is alive is kept. -> {removed: string[], killed: string[], kept: {slug, why}[], badMarkers: string[]}

Returns

object

badMarkers

badMarkers: any[] = []

kept

kept: any[] = []

killed

killed: any[] = []

removed

removed: any[] = []

start()

start(opts?): Promise<{ code: string; error: string; ok: boolean; status: number; } | { code?: undefined; done: Promise<any>; error?: undefined; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; status?: undefined; }>

Validate and start. token (optional, a string) is a one-time access token for a private repository: it is validated, held as a Buffer, given to the process only through the per-job askpass helper, and zeroed when the job ends. -> {ok:true, job} | {ok:false, status, code, error}

Parameters
opts?
Returns

Promise<{ code: string; error: string; ok: boolean; status: number; } | { code?: undefined; done: Promise<any>; error?: undefined; job: { branch?: any; bytes: any; code?: any; dir?: any; error?: any; finishedAt: any; id: any; kind: string; log: any; name: any; private: boolean; progress: any; startedAt: any; state: any; title: string; url: any; via?: string; }; ok: boolean; status?: undefined; }>


dirBytes()#

dirBytes(dir, limit?): number

Defined in: ui/server/src/cloneJobs.mjs:69

Bytes under dir (lstat only, never follows a link), stopping early once limit is passed.

Parameters#

dir

any

limit?

number = Infinity

Returns#

number


killLiveCloneGroups()#

killLiveCloneGroups(): void

Defined in: ui/server/src/cloneJobs.mjs:151

SIGKILL every live clone's process group. Registered on exit and on the terminating signals; exported for tests.

Returns#

void


liveCloneChildren()#

liveCloneChildren(): number

Defined in: ui/server/src/cloneJobs.mjs:159

How many clone children are alive right now (test seam).

Returns#

number


markerPath()#

markerPath(root, slug): any

Defined in: ui/server/src/cloneJobs.mjs:140

Parameters#

root

any

slug

any

Returns#

any


stampPath()#

stampPath(dest): any

Defined in: ui/server/src/cloneJobs.mjs:204

Parameters#

dest

any

Returns#

any


unsafeConfigKeys()#

unsafeConfigKeys(keys): any[]

Defined in: ui/server/src/cloneJobs.mjs:50

The UNSAFE_PULL_CONFIG patterns that keys (git config keys, section[.subsection].name) match; [] when none.

Parameters#

keys

any

Returns#

any[]