Compare commits

...

6 Commits

Author SHA1 Message Date
deac844d02 Add testing protocol. 2020-09-05 19:16:00 -05:00
80a3ba4621 Add more descriptive message for 404s. 2019-02-21 23:46:45 -06:00
Jonathan Bernard
774d0b446f Fix typo in active runs API, add functional test for same. 2018-12-26 23:43:44 -06:00
Jonathan Bernard
ee1147a1a5 Add configurability of the server port. 2018-12-23 18:20:22 -06:00
Jonathan Bernard
186b7d5b29 Fix /ping unit test (now /version) 2018-12-23 17:42:43 -06:00
Jonathan Bernard
52eaa63f25 Rework build configuration to take advantage of new built-in docker build capabilities. 2018-12-23 17:39:04 -06:00
12 changed files with 87 additions and 30 deletions

View File

@ -3,8 +3,7 @@ import cliutils, docopt, os, sequtils, strutils, tempfile, uuids
import strawbosspkg/configuration import strawbosspkg/configuration
import strawbosspkg/core import strawbosspkg/core
import strawbosspkg/server import strawbosspkg/server
import strawbosspkg/version
let SB_VER = "0.5.0"
proc logProcOutput*(outMsg, errMsg: TaintedString, cmd: string) = proc logProcOutput*(outMsg, errMsg: TaintedString, cmd: string) =
let prefix = if cmd.len > 0: cmd & ": " else: "" let prefix = if cmd.len > 0: cmd & ": " else: ""
@ -26,7 +25,7 @@ Options
(strawboss.config.json). (strawboss.config.json).
""" """
let args = docopt(doc, version = "strawboss v" & SB_VER) let args = docopt(doc, version = "strawboss v" & SB_VERSION)
let cfgFile = if args["--config-file"]: $args["--config-file"] let cfgFile = if args["--config-file"]: $args["--config-file"]
else: "strawboss.config.json" else: "strawboss.config.json"

View File

@ -58,6 +58,7 @@ type
debug*: bool debug*: bool
logLevel*: Level logLevel*: Level
pathToExe*: string pathToExe*: string
port*: int
projects*: seq[ProjectDef] projects*: seq[ProjectDef]
pwdCost*: int8 pwdCost*: int8
users*: seq[UserRef] users*: seq[UserRef]
@ -83,6 +84,7 @@ proc `==`*(a, b: StrawBossConfig): bool =
a.buildDataDir == b.buildDataDir and a.buildDataDir == b.buildDataDir and
a.authSecret == b.authSecret and a.authSecret == b.authSecret and
a.pwdCost == b.pwdCost and a.pwdCost == b.pwdCost and
a.port == b.port and
a.maintenancePeriod == b.maintenancePeriod and a.maintenancePeriod == b.maintenancePeriod and
a.logLevel == b.logLevel and a.logLevel == b.logLevel and
sameContents(a.users, b.users) and sameContents(a.users, b.users) and
@ -144,6 +146,7 @@ proc parseStrawBossConfig*(jsonCfg: JsonNode): StrawBossConfig =
buildDataDir: jsonCfg.getIfExists("buildDataDir").getStr("build-data"), buildDataDir: jsonCfg.getIfExists("buildDataDir").getStr("build-data"),
authSecret: jsonCfg.getOrFail("authSecret", "strawboss config").getStr, authSecret: jsonCfg.getOrFail("authSecret", "strawboss config").getStr,
debug: jsonCfg.getIfExists("debug").getBool(false), debug: jsonCfg.getIfExists("debug").getBool(false),
port: int(jsonCfg.getIfExists("port").getInt(8180)),
pwdCost: int8(jsonCfg.getOrFail("pwdCost", "strawboss config").getInt), pwdCost: int8(jsonCfg.getOrFail("pwdCost", "strawboss config").getInt),
projects: jsonCfg.getIfExists("projects").getElems.mapIt(parseProjectDef(it)), projects: jsonCfg.getIfExists("projects").getElems.mapIt(parseProjectDef(it)),
maintenancePeriod: int(jsonCfg.getIfExists("maintenancePeriod").getInt(10000)), maintenancePeriod: int(jsonCfg.getIfExists("maintenancePeriod").getInt(10000)),
@ -296,6 +299,7 @@ proc `%`*(cfg: StrawBossConfig): JsonNode =
"buildDataDir": cfg.buildDataDir, "buildDataDir": cfg.buildDataDir,
"authSecret": cfg.authSecret, "authSecret": cfg.authSecret,
"debug": cfg.debug, "debug": cfg.debug,
"port": cfg.port,
"projects": %cfg.projects, "projects": %cfg.projects,
"pwdCost": cfg.pwdCost, "pwdCost": cfg.pwdCost,
"maintenancePeriod": cfg.maintenancePeriod, "maintenancePeriod": cfg.maintenancePeriod,

View File

@ -7,7 +7,7 @@ from asyncnet import send
from re import re, find from re import re, find
from timeutils import trimNanoSec from timeutils import trimNanoSec
import ./configuration, ./core import ./configuration, ./core, ./version
type type
Session = object Session = object
@ -161,13 +161,13 @@ proc start*(cfg: StrawBossConfig): void =
var workers: seq[Worker] = @[] var workers: seq[Worker] = @[]
settings: settings:
port = Port(8180) port = Port(cfg.port)
appName = "/api" appName = "/api"
routes: routes:
get "/ping": get "/version":
resp($(%"pong"), JSON) resp($(%("strawboss v" & SB_VERSION)), JSON)
post "/auth-token": post "/auth-token":
var uname, pwd: string var uname, pwd: string
@ -180,7 +180,9 @@ proc start*(cfg: StrawBossConfig): void =
try: try:
let authToken = makeAuthToken(cfg, uname, pwd) let authToken = makeAuthToken(cfg, uname, pwd)
resp($(%authToken), JSON) resp($(%authToken), JSON)
except: jsonResp(Http401, getCurrentExceptionMsg()) except:
jsonResp(Http401, getCurrentExceptionMsg())
if ctx.cfg.debug: echo getStackTrace()
get "/verify-auth": get "/verify-auth":
checkAuth() checkAuth()
@ -266,17 +268,16 @@ proc start*(cfg: StrawBossConfig): void =
checkAuth() checkAuth()
var details = ""
try: try:
let activeRuns = workers let activeRuns = workers
.filterIt(it.process.running and it.projectName == @"projectName") .filterIt(it.process.running and it.projectName == @"projectName")
.mapIt(cfg.getRun(@"projecName", $it.runId)); .mapIt(cfg.getRun(@"projectName", $it.runId));
resp($(%activeRuns), JSON) resp($(%activeRuns), JSON)
except NotFoundException:
jsonResp(Http404, getCurrentExceptionMsg())
except: except:
try: raise getCurrentException() json500Resp(getCurrentException(), "problem loading active runs")
except NotFoundException:
jsonResp(Http404, getCurrentExceptionMsg())
except:
json500Resp(getCurrentException(), "problem loading active runs")
get "/project/@projectName/run/@runId": get "/project/@projectName/run/@runId":
## Details for a specific run ## Details for a specific run
@ -446,7 +447,7 @@ proc start*(cfg: StrawBossConfig): void =
get re".*": get re".*":
jsonResp(Http404) jsonResp(Http404, "URL [" & request.path & "] is not present on this server.")
post re".*": post re".*":
jsonResp(Http404) jsonResp(Http404)

View File

@ -0,0 +1,2 @@
const SB_VERSION* = "0.5.1"

View File

@ -6,6 +6,7 @@
{ "name": "bob@builder.com", "hashedPwd": "$2a$11$lVZ9U4optQMhzPh0E9A7Yu6XndXblUF3gCa.zmEvJy4F.4C4718b." }, { "name": "bob@builder.com", "hashedPwd": "$2a$11$lVZ9U4optQMhzPh0E9A7Yu6XndXblUF3gCa.zmEvJy4F.4C4718b." },
{ "name": "sam@sousa.com", "hashedPwd": "testvalue" } { "name": "sam@sousa.com", "hashedPwd": "testvalue" }
], ],
"port": 8180,
"pwdCost": 11, "pwdCost": 11,
"projects": [ "projects": [
{ "name": "dummy-project", { "name": "dummy-project",

View File

@ -2,6 +2,7 @@ import cliutils, httpclient, json, os, osproc, sequtils, strutils, tempfile,
times, unittest, untar, uuids times, unittest, untar, uuids
from langutils import sameContents from langutils import sameContents
from algorithm import sorted
import ../testutil import ../testutil
import ../../../main/nim/strawbosspkg/configuration import ../../../main/nim/strawbosspkg/configuration
@ -205,9 +206,40 @@ suite "strawboss server":
# Run the "build" step # Run the "build" step
# Kick off a build that depends on "build" (which was run in the last test) # Kick off a build that depends on "build" (which was run in the last test)
# TODO test "kick off multiple runs and check the list of active runs via the API":
#test "kick off multiple runs and check the list of active runs via the API": let http = newAuthenticatedHttpClient(apiBase, "bob@builder.com", "password")
# check false
# Kick off multiple runs of the "long-running" job
let queuedRuns = toSeq((1..3)).map(proc (idx: int): Run =
let resp = http.post(apiBase & "/project/" & testProjName & "/step/long-running/run/0.3.1")
check resp.status.startsWith("200")
return parseRun(parseJson(resp.body)))
# Collect run ids.
let runIds = queuedRuns.mapIt($(it.id)).sorted(cmpIgnoreCase)
# Check on the runs
let getActiveResp = http.get(apiBase & "/project/" & testProjName & "/runs/active")
check getActiveResp.status.startsWith("200")
let activeRuns = parseJson(getActiveResp.body).getElems().mapIt(parseRun(it))
let activeRunIds = activeRuns.mapIt($(it.id)).sorted(cmpIgnoreCase)
# Make sure we see all runs in the active state.
check runIds == activeRunIds
let completedRuns = runIds.map(proc (runId: string): Run =
return http.waitForBuild(apiBase, testProjName, runId))
# Make sure all are completed and all are accounted for
check completedRuns.allIt(it.status.state == BuildState.complete)
check completedRuns.mapIt($(it.id)).sorted(cmpIgnoreCase) == runIds;
# Check that there are no more active runs
let getActiveResp2 = http.get(apiBase & "/project/" & testProjName & "/runs/active")
let remainingActiveRuns = parseJson(getActiveResp2.body).getElems().mapIt(parseRun(it))
check remainingActiveRuns.len == 0
# Last-chance catch to kill the server in case some test err'ed and didn't # Last-chance catch to kill the server in case some test err'ed and didn't
# reach it's teardown handler # reach it's teardown handler

View File

@ -6,6 +6,7 @@ from langutils import sameContents
import ../testutil import ../testutil
import ../../../main/nim/strawbosspkg/configuration import ../../../main/nim/strawbosspkg/configuration
import ../../../main/nim/strawbosspkg/server import ../../../main/nim/strawbosspkg/server
import ../../../main/nim/strawbosspkg/version
let apiBase = "http://localhost:8180/api" let apiBase = "http://localhost:8180/api"
let cfgFilePath = "src/test/json/strawboss.config.json" let cfgFilePath = "src/test/json/strawboss.config.json"
@ -40,11 +41,11 @@ suite "strawboss server":
let tok = toJWT(cfg, session) let tok = toJWT(cfg, session)
check fromJWT(cfg, tok) == session check fromJWT(cfg, tok) == session
test "ping": test "version":
let resp = http.get(apiBase & "/ping") let resp = http.get(apiBase & "/version")
check: check:
resp.status.startsWith("200") resp.status.startsWith("200")
resp.body == "\"pong\"" resp.body == "\"strawboss v" & SB_VERSION & "\""
test "fail auth": test "fail auth":
let resp = http.post(apiBase & "/auth-token", let resp = http.post(apiBase & "/auth-token",

@ -1 +1 @@
Subproject commit 127be8f66fcc6d4d223acf56668d42ff9c37bfb0 Subproject commit ab883bd9602a1373347a23c8bee4ed28dd475aec

Binary file not shown.

View File

@ -1,7 +1,7 @@
# Package # Package
bin = @["strawboss"] bin = @["strawboss"]
version = "0.5.0" version = "0.5.1"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "My personal continious integration worker." description = "My personal continious integration worker."
license = "MIT" license = "MIT"
@ -44,3 +44,8 @@ task test, "Runs both the unit and functional test suites.":
echo "\nRunning functional tests." echo "\nRunning functional tests."
echo "-------------------------" echo "-------------------------"
exec "src/test/nim/run_functional_tests" exec "src/test/nim/run_functional_tests"
task dist, "Creates distributable package.":
exec "nimble build"
mkdir "dist"
exec "cp strawboss strawboss.config.json example.json dist/."

View File

@ -1,24 +1,25 @@
{ {
"name": "strawboss", "name": "strawboss",
"containerImage": "nimlang/nim:0.19.0",
"steps": { "steps": {
"compile": { "compile": {
"artifacts": ["strawboss"], "artifacts": ["strawboss"],
"stepCmd": "docker run -v `pwd`:/usr/src/strawboss -w /usr/src/strawboss jdbernard/nim:0.17.2 nimble install" "stepCmd": "nimble build"
}, },
"unittest": { "unittest": {
"depends": ["compile"], "depends": ["compile"],
"stepCmd": "docker run -v `pwd`:/usr/src/strawboss -v $compile_DIR:/usr/build/strawboss -w /usr/src/strawboss -i jdbernard/nim:0.17.2 /bin/bash", "stepCmd": "/bin/bash",
"cmdInput": [ "cmdInput": [
"cp /usr/build/strawboss/strawboss .", "cp $compile_DIR/strawboss .",
"nimble install --depsOnly", "nimble install --depsOnly",
"nim c -r src/test/nim/run_unit_tests" "nim c -r src/test/nim/run_unit_tests"
] ]
}, },
"functest": { "functest": {
"depends": ["compile"], "depends": ["compile"],
"stepCmd": "docker run -v `pwd`:/usr/src/strawboss -v $compile_DIR:/usr/build/strawboss -w /usr/src/strawboss -i jdbernard/nim:0.17.2 /bin/bash", "stepCmd": "/bin/bash",
"cmdInput": [ "cmdInput": [
"cp /usr/build/strawboss/strawboss .", "cp $compile_DIR/strawboss .",
"nimble install --depsOnly", "nimble install --depsOnly",
"nim c -r src/test/nim/run_functional_tests" "nim c -r src/test/nim/run_functional_tests"
] ]
@ -26,9 +27,9 @@
"build": { "build": {
"artifacts": ["strawboss-$VERSION.zip"], "artifacts": ["strawboss-$VERSION.zip"],
"depends": ["compile", "unittest", "functest"], "depends": ["compile", "unittest", "functest"],
"stepCmd": "docker run -v `pwd`:/usr/src/strawboss -v $compile_DIR:/usr/build/strawboss -w /usr/src/strawboss -i jdbernard/nim:0.17.2 /bin/bash", "stepCmd": "/bin/bash",
"cmdInput": [ "cmdInput": [
"cp /usr/build/strawboss/strawboss .", "cp $compile_DIR/strawboss .",
"zip strawboss-$VERSION.zip strawboss strawboss.config.json example.json src/main/systemd/strawboss.service" "zip strawboss-$VERSION.zip strawboss strawboss.config.json example.json src/main/systemd/strawboss.service"
] ]
} }

11
test-spec.txt Normal file
View File

@ -0,0 +1,11 @@
Run a build. Look for:
- Run request archived
- Output logs archived with the run request
- Artifacts archived in the build-data directory.
- Configuration for that version archived in configurations directory.
- Status for that version archived in the status directory
Run the build again for the same project and build ref:
- Build should be skipped.
- Run request should be archived.