Reworking runs to include an id, save the run request.

This commit is contained in:
Jonathan Bernard 2017-05-11 10:51:06 -05:00
parent e2c3aeca09
commit 3d8454d486
6 changed files with 75 additions and 20 deletions

View File

@ -1,4 +1,4 @@
import docopt, os, sequtils, tempfile
import docopt, os, sequtils, tempfile, uuids
import strawbosspkg/private/util
import strawbosspkg/configuration
@ -31,6 +31,9 @@ Options
-r --reference <ref> Build the project at this commit reference.
-i --run-id <id> Use the given UUID as the run ID. If not given, a
new UUID is generated for this run.
-w --workspace <workspace> Use the given directory as the build workspace.
"""
@ -51,14 +54,17 @@ Options
if args["run"]:
let req = RunRequest(
projectName: $args["<project>"],
stepName: $args["<step>"],
buildRef: if args["--reference"]: $args["--reference"] else: nil,
forceRebuild: args["--force-rebuild"],
workspaceDir: if args["--workspace"]: $args["<workspace>"] else: mkdtemp())
let wkspDir = if args["--workspace"]: $args["--workspace"] else: mkdtemp()
try:
let req = RunRequest(
id: if args["--run-id"]: parseUUID($args["--run-id"]) else: genUUID(),
projectName: $args["<project>"],
stepName: $args["<step>"],
buildRef: if args["--reference"]: $args["--reference"] else: nil,
forceRebuild: args["--force-rebuild"],
workspaceDir: wkspDir)
let status = core.runStep(cfg, req, logProcOutput)
if status.state == "failed": raiseEx status.details
echo "strawboss: build passed."
@ -66,7 +72,7 @@ Options
echo "strawboss: build FAILED: " & getCurrentExceptionMsg() & "."
quit(QuitFailure)
finally:
if existsDir(req.workspaceDir): removeDir(req.workspaceDir)
if existsDir(wkspDir): removeDir(wkspDir)
elif args["serve"]: server.start(cfg)

View File

@ -1,4 +1,4 @@
import logging, json, os, nre, sequtils, strtabs, tables, times
import logging, json, os, nre, sequtils, strtabs, tables, times, uuids
import private/util
from langutils import sameContents
@ -25,6 +25,7 @@ type
envVars*: StringTableRef
RunRequest* = object
id*: UUID
projectName*, stepName*, buildRef*, workspaceDir*: string
forceRebuild*: bool
@ -67,6 +68,15 @@ proc `==`*(a, b: StrawBossConfig): bool =
sameContents(a.users, b.users) and
sameContents(a.projects, b.projects)
proc `==`*(a, b: RunRequest): bool =
result =
a.id == b.id and
a.projectName == b.projectName and
a.stepName == b.stepName and
a.buildRef == b.buildRef and
a.workspaceDir == b.workspaceDir and
a.forceRebuild == b.forceRebuild
# Util methods on custom types
proc findProject*(cfg: StrawBossConfig, projectName: string): ProjectDef =
let candidates = cfg.projects.filterIt(it.name == projectName)
@ -182,12 +192,9 @@ proc loadBuildStatus*(statusFile: string): BuildStatus =
state: jsonObj.getOrFail("state", "build status").getStr,
details: jsonObj.getIfExists("details").getStr("") )
# TODO: unused and untested, add tests if we start using this
proc parseRunRequest*(reqStr: string): RunRequest =
let reqJson = parseJson(reqStr)
proc parseRunRequest*(reqJson: JsonNode): RunRequest =
result = RunRequest(
id: parseUUID(reqJson.getOrFail("id", "RunRequest").getStr),
projectName: reqJson.getOrFail("projectName", "RunRequest").getStr,
stepName: reqJson.getOrFail("stepName", "RunRequest").getStr,
buildRef: reqJson.getOrFail("buildRef", "RunRequest").getStr,
@ -213,6 +220,7 @@ proc `%`*(p: ProjectDef): JsonNode =
proc `%`*(req: RunRequest): JsonNode =
result = %* {
"id": $req.id,
"projectName": req.projectName,
"stepName": req.stepName,
"buildRef": req.buildRef,

View File

@ -168,6 +168,14 @@ proc runStep*(cfg: StrawBossConfig, req: RunRequest,
# Find the project definition
let projectDef = cfg.findProject(req.projectName)
# Make sure our directory in the artifacts repo exists
if not existsDir(cfg.artifactsRepo & "/" & projectDef.name & "/run-requests"):
createDir(cfg.artifactsRepo & "/" & projectDef.name & "/run-requests")
# Save the run request
writeFile(cfg.artifactsRepo & "/" & projectDef.name &
"/run-requests/" & $req.id & ".json", $req)
# Read in the existing system environment
var env = loadEnv()
env["GIT_DIR"] = ".git"

View File

@ -1,9 +1,10 @@
import algorithm, asyncdispatch, bcrypt, jester, json, jwt, logging, os, osproc,
sequtils, strutils, tempfile, times, unittest
sequtils, strutils, tempfile, times, unittest, uuids
import ./configuration, ./core, private/util
type Worker = object
runId*: UUID
process*: Process
workingDir*: string
@ -76,10 +77,11 @@ proc spawnWorker(cfg: StrawBossConfig, req: RunRequest): Worker =
let dir = mkdtemp()
var args = @["run", req.projectName, req.stepName, "-r", req.buildRef,
"-w", dir, "-c", cfg.filePath]
"-w", dir, "-c", cfg.filePath, "-i", req.id]
if req.forceRebuild: args.add("-f")
debug "Launching worker: " & cfg.pathToExe & " " & args.join(" ")
result = Worker(
runId: req.id,
process: startProcess(cfg.pathToExe, ".", args, loadEnv(), {poUsePath}),
workingDir: dir)
@ -238,7 +240,20 @@ proc start*(cfg: StrawBossConfig): void =
## List all runs
checkAuth(); if not authed: return true
# Make sure we know about that project
var project: ProjectDef
try: project = cfg.findProject(@"projectName")
except: resp(Http404, makeJsonResp(Http404, getCurrentExceptionMsg()), JSON)
let runsDir = cfg.artifactsRepo & "/" & project.name & "/runs"
if not existsDir(runsDir): resp("[]", JSON)
let runPaths = toSeq(walkFiles(runsDir & "/*.json"))
let runRequests = runPaths.mapIt(parseRunRequest(parseFile(it)))
resp($(%runRequests), JSON)
# TODO
resp(Http501, makeJsonResp(Http501), JSON)
@ -279,7 +294,8 @@ proc start*(cfg: StrawBossConfig): void =
checkAuth(); if not authed: return true
workers.add(spawnWorker(RunRequest(
let runRequest = RunRequest(
id: genUUID(),
projectName: @"projectName",
stepName: @"stepName",
buildRef: if @"buildRef" != "": @"buildRef" else: nil,

View File

@ -1,4 +1,5 @@
import json, strtabs, tables, unittest
import json, strtabs, tables, unittest, uuids
from langutils import sameContents
import ../../../main/nim/strawbosspkg/configuration
@ -18,6 +19,18 @@ suite "load and save configuration objects":
defaultBranch: "deploy",
envVars: newStringTable("VAR1", "value", modeCaseInsensitive))
test "parseRunRequest":
let rr1 = RunRequest(
id: genUUID(),
projectName: testProjDef.name,
stepName: "build",
buildRef: "master",
workspaceDir: "/no-real/dir",
forceRebuild: true)
let rrStr = $rr1
let rr2 = parseRunRequest(parseJson(rrStr))
check rr1 == rr2
test "parseProjectDef":
let pd = parseProjectDef(parseJson(testProjDefStr))

View File

@ -9,10 +9,14 @@ srcDir = "src/main/nim"
# Dependencies
requires @["nim >= 0.16.1", "docopt >= 0.1.0", "tempfile", "jester", "bcrypt", "untar"]
requires @["nim >= 0.16.1", "docopt >= 0.1.0", "tempfile", "jester", "bcrypt",
"untar", "uuids"]
requires "https://github.com/yglukhov/nim-jwt"
requires "https://git.jdb-labs.com/jdb/nim-lang-utils.git"
# Tasks
#
task functest, "Runs the functional test suite.":
exec "nim c -r src/test/nim/run_functional_tests.nim"