Code Monkey home page Code Monkey logo

laminar's Introduction

Laminar CI status

Laminar (https://laminar.ohwg.net) is a lightweight and modular Continuous Integration service for Linux. It is self-hosted and developer-friendly, eschewing a configuration UI in favour of simple version-controllable configuration files and scripts.

Laminar encourages the use of existing GNU/Linux tools such as bash and cron instead of reinventing them.

Although the status and progress front-end is very user-friendly, administering a Laminar instance requires writing shell scripts and manually editing configuration files. That being said, there is nothing esoteric here and the guide should be straightforward for anyone with even very basic Linux server administration experience.

See the website and the documentation for more information.

Building from source

First install development packages for capnproto (version 0.7.0 or newer), rapidjson, sqlite and boost (for the header-only multi_index_container library) from your distribution's repository or other source.

On Debian Bullseye, this can be done with:

sudo apt install capnproto cmake g++ libboost-dev libcapnp-dev libsqlite3-dev \
  rapidjson-dev zlib1g-dev pkg-config

Then compile and install laminar with:

git clone https://github.com/ohwgiles/laminar.git
cd laminar
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr
make -j "$(nproc)"
# Warning: the following will overwrite an existing /etc/laminar.conf
sudo make install

make install includes a systemd unit file. If you intend to use it, consider creating a new user laminar or modifying the user specified in the unit file.

Packaging for distributions

The pkg directory contains shell scripts which use docker to build native packages (deb,rpm) for common Linux distributions. Note that these are very simple packages which may not completely conform to the distribution's packaging guidelines, however they may serve as a starting point for creating an official package, or may be useful if the official package lags.

Contributing

Issues and pull requests via GitHub are most welcome. All pull requests must adhere to the Developer Certificate of Origin.

laminar's People

Contributors

alexmyczko avatar benoitjpnet avatar cweagans avatar cynerd avatar datagrok avatar donkult avatar ferki avatar geraldolsribeiro avatar jbglaw avatar limaa avatar lucki avatar marian-cingel avatar maxcrees avatar meskio avatar michael-s avatar mitya57 avatar neovance avatar ohwgiles avatar palica avatar sbrl avatar seifertm avatar stbuehler avatar valicek1 avatar xlii-chl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laminar's Issues

Strange time counter

When starting a job, amount of time passed starts on negative value. Looks very strange.

Also, how is estimate progress calculated? Maybe this is connected.

notifications

are you planning to extend the tool with some notifications? not only browser notifications, but support for external stuff?

Laminard terminates

Hi I am trying to run laminar in a container (LXD gentoo with OpenRC). And this is what I am getting as output.

The container is named laminar-ci it has internet access,

`

laminard

terminate called after throwing an instance of 'kj::ExceptionImpl'
what(): kj/async-io-unix.c++:748: failed: DNS lookup failed.; params.host = unix-abstract; params.service = laminar; gai_strerror(status) = Servname not supported for ai_socktype
stack: 0x7f1abdbe3063 0x7f1abde311c1 0x7f1abde28e2d 0x7f1abde2963f 0x7f1abde11bb2 0x7f1abde23a10 0x42af70 0x42e99e 0x7f1abde18286 0x7f1abde117cb 0x7f1abde14e75 0x431d5f 0x42b4e2 0x4582eb 0x4297f8 0x7f1abc455f10 0x4299e9
Aborted
`
So there is some problem with dns? Can you please help me? Thank you

Web UI not functional behind reverse proxy

When the laminar web UI is behind a reverse proxy (nginx), the website does not work. It does not show any UI elements:
screenshot

The means of connecting to the website does not seem to have any impact. I tried connecting via a unix socket and via a network socket. The nginx rule used to forward requests to laminar is simple:

location / {
    #proxy_pass http://unix:/var/lib/laminar/laminard.sock;
    proxy_pass http://example.com:8081;
}

When I connect to http://example.com:8081 directly, the web UI is displayed correctly.

laminarc commands: queue/start/run

Replace the existing trigger (which queues a job) and start (which runs a job to completion) with queue (queues a job), start (blocks until job starts) and run (blocks until completion)

Laminard crashing under load

So I am creating jobs every 10 seconds like this:

for i in `cat $(wc -l pkgcat/*|sort|awk '{ print $2 }'|grep -v total |head -10)` ;do LAMINAR_REASON="$i" laminarc trigger fun-prime PKG=$i;sleep 10;done

The input of i$ is something like this:

cat $(wc -l pkgcat/*|sort|awk '{ print $2 }'|grep -v total |head -10)
app-antivirus/clamav
app-antivirus/clamav-unofficial-sigs
app-antivirus/skyldav
x11-base/xorg-drivers    
x11-base/xorg-server
x11-base/xorg-x11  
....

The scipt fun-prime is starting a container and then building the package inside the LXD container.
Can supply those as well if you need them.

So there is a new run added to the job for a different package.

This is inside the laminard.log:

cat /var/log/laminard 
terminate called after throwing an instance of 'kj::ExceptionImpl'
  what():  laminar.cpp:376: failed: expected siginfo->ssi_signo == SIGCHLD
stack: 0x42be9e 0x42dde7 0x7fa345d8a544 0x42ebec 0x7fa345d918bd 0x7fa345d89ff9 0x7fa345d8e004 0x43284a 0x42b6d9 0x4574b1 0x429877 0x7fa3446866fb 0x429a98

executors question

I have:

nodes/default.conf
EXECUTORS=2

nodes/emerge.conf
EXECUTORS=1
TAGS=emerge

but laminar spins up 3 jobs for a job tagged emerge using jobs/job.conf

Am I using it wrong?

Thank you

Job execution timeout

It should be possible to set a maximum execution time for any job, after which laminar should abort it. Depends on #29

No logs in Web UI

Trying to grasp laminar's power, but something went wrong... I queued a "hello" job, tried to run it 5 times, and received no log output, when I looked into Web UI!

Tried to run it 6th time, received some log output while the job is still running, but after reloading, the job is shown like it never was - everything is NaN or undefined, and no logs are saved.

Maybe it's a bug, maybe it's intentional, but how to make laminar at least save the job logs and stats? By the way, the "Last success" and "Last build" stats on job screen also suffer from this.

Queued runs don't survive page refresh on :8080/jobs/job_name page

When there are jobs, being added to queue and you are on the jobs page the queued jobs increment and get shown correctly. Once you refresh the page or navigate away and come back the queued jobs are not shown. If there are even more jobs being added to the queue then the queue starts counting from 1 again, which is not correct.

passing variable with space

how should I pass variable with space? eg. USE="this that" because every time I use laminarc set USE=$USE it gets truncated to USE='"this'

am I doing something wrong?

LAMINAR_KEEP_RUNDIR should keep the <n> most recent job runs

The current behaviour of LAMINAR_KEEP_RUNDIR is that if the env variable is set, all job runs will be preserved. This leads to jobs piling up on the disk, which is why this setting is disabled in my setup. However, if I need to inspect the environment of a failed job, I have to change the configuration, restart laminar, and re-run the failing job.

I suggest that LAMINAR_KEEP_RUNDIR supports integer values. The integer represents the number of run directories that will be preserved.
For example: LAMINAR_KEEP_RUNDIR=3 will preserve the three most recent run directories for every job.

This would allow me to enable the setting permanently. It would be easier to inspect and debug the environment in which a job failed without having to re-configure and restart laminar.

I am bringing this idea up, because it seems somewhat related to #18 .

Badge url

A job's current status could be served as a badge, e.g. laminar:8080/jobs/JOB/badge.svg. Remember to set a short cache period.

laminar closing connection on (larger?) files

When I am trying to download a file from laminar's archive I am getting this:

This is even directly downloading

wget http://laminar.lxd:8080/archive/fun-prime/89/dev-db/mariadb-10.2.9.tbz2
--2018-04-12 08:29:42--  http://laminar.lxd:8080/archive/fun-prime/89/dev-db/mariadb-10.2.9.tbz2
Resolving laminar.lxd... 127.0.0.1
Connecting to laminar.lxd|127.0.0.1|:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 43209261 (41M)
Saving to: ‘mariadb-10.2.9.tbz2’

mariadb-10.2.9.tbz2                                 8%[========>                                                                                                   ]   3.56M  --.-KB/s    in 0.01s   

2018-04-12 08:29:42 (320 MB/s) - Connection closed at byte 3732424. Retrying.

--2018-04-12 08:29:43--  (try: 2)  http://laminar.lxd:8080/archive/fun-prime/89/dev-db/mariadb-10.2.9.tbz2
Connecting to laminar.lxd|127.0.0.1|:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 43209261 (41M)
Saving to: ‘mariadb-10.2.9.tbz2’

mariadb-10.2.9.tbz2                                20%[====================>                                                                                       ]   8.37M  --.-KB/s    in 0.02s   

2018-04-12 08:29:43 (517 MB/s) - Connection closed at byte 8774615. Retrying.

^C

I am running without proxy, so :8080 is directly laminar listening for requests.

But running with proxy doesn't make it better.

2018-04-12 16:39:16 (602 KB/s) - Connection closed at byte 3404021. Retrying.

How can I help to debug it for you some more?

`laminarc start` output could point to job run (URL/id)

When triggering child jobs, as described by [1], the only returned information about child job's result is exit code ([2]). Having lots of parent and child jobs executed it's easy (at least for me) to lose track which child job "belongs" to the parent one. Thus I think it would be cool for start result to contain also any "pointer" to the child job.

Examples of what I have in mind:

$ laminarc start ajob
75
$ echo $?
0
  • feedback with job URL. This probably involves laminard to become self-conscious about its URL, and somehow it would need to became configurable - not sure whether this is cool approach?
$ laminarc start ajob
http://laminar.example/jobs/ajob/75
$ echo $?
0

[1] http://laminar.ohwgiles.documentup.com/#job-chains
[2] https://github.com/ohwgiles/laminar/blob/master/src/laminar.capnp#L26

Unable to build in debian:stable

Hi, I have tried to rebuild last version (commit 9c25681) from git with script from this repo and it failed.

I think, it is due to some old lib or something similar, but I'm not familiar with it enough to find, where issue is. Any kick possible?
Thanks, Valicek1

Error (from command make -j4 in debian docker script, no errors in steps before).

root@95e46937385e:/build/laminar# make -j4
[  8%] Generating laminar.capnp.c++, laminar.capnp.h
[  8%] Generating css/bootstrap.min.css.z
[ 11%] Generating index.html.z
[  8%] Generating laminar.capnp.c++, laminar.capnp.h
[ 13%] Generating js/app.js.z
[ 16%] Generating favicon.ico.z
[ 19%] Generating favicon-152.png.z
[ 25%] Generating icon.png.z
[ 25%] Generating js/vue-router.min.js.z
Scanning dependencies of target laminarc
[ 27%] Generating js/vue.min.js.z
[ 33%] Generating js/ansi_up.js.z
[ 33%] Generating js/Chart.min.js.z
[ 36%] Generating js/Chart.HorizontalBar.js.z
[ 41%] Generating css/bootstrap.min.css.o
[ 41%] Building CXX object CMakeFiles/laminarc.dir/src/client.cpp.o
[ 44%] Building CXX object CMakeFiles/laminarc.dir/laminar.capnp.c++.o
[ 47%] Generating index.html.o
[ 50%] Generating js/app.js.o
[ 52%] Generating favicon.ico.o
[ 55%] Generating favicon-152.png.o
[ 58%] Generating icon.png.o
[ 61%] Generating js/vue-router.min.js.o
[ 63%] Generating js/vue.min.js.o
[ 66%] Generating js/ansi_up.js.o
[ 69%] Generating js/Chart.min.js.o
[ 72%] Generating js/Chart.HorizontalBar.js.o
Scanning dependencies of target laminard
[ 77%] Building CXX object CMakeFiles/laminard.dir/src/database.cpp.o
[ 77%] Building CXX object CMakeFiles/laminard.dir/src/main.cpp.o
[ 80%] Building CXX object CMakeFiles/laminard.dir/src/server.cpp.o
[ 83%] Building CXX object CMakeFiles/laminard.dir/src/laminar.cpp.o
[ 86%] Linking CXX executable laminarc
[ 86%] Built target laminarc
[ 88%] Building CXX object CMakeFiles/laminard.dir/src/conf.cpp.o
[ 91%] Building CXX object CMakeFiles/laminard.dir/src/resources.cpp.o
[ 94%] Building CXX object CMakeFiles/laminard.dir/src/run.cpp.o
[ 97%] Building CXX object CMakeFiles/laminard.dir/laminar.capnp.c++.o
/build/laminar/src/server.cpp: In member function 'void Server::start()':
/build/laminar/src/server.cpp:438:16: error: 'class kj::TaskSet' has no member named 'onEmpty'
     childTasks.onEmpty().wait(ioContext.waitScope);
                ^~~~~~~
/build/laminar/src/server.cpp:440:25: error: 'class kj::WaitScope' has no member named 'poll'
     ioContext.waitScope.poll();
                         ^~~~
CMakeFiles/laminard.dir/build.make:205: recipe for target 'CMakeFiles/laminard.dir/src/server.cpp.o' failed
make[2]: *** [CMakeFiles/laminard.dir/src/server.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/laminard.dir/all' failed
make[1]: *** [CMakeFiles/laminard.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2

Web UI: notify and reconnect interrupted connections

If the connection from the browser to laminard is interrupted (e.g. server dies, or reverse proxy times out the websocket link), the browser should attempt to reconnect, and display a notification if this fails

In-browser notification

Would be nice if an open Laminar tab in browser could ping you with a browser notification when something finishes cooking up.

I hope it doesn't break your minimalistic approach (which is cool, because Laminar is blazing fast on a low-power Raspberry Pi!), but would be probably useful for me, as my job notifier doesn't work for some reason...

High visibility job group

It should be possible to display each tab group on the jobs page in a high-visibility mode for displaying on large screens in the office

Malformed URL when setting external artefact server

When I set LAMINAR_ARCHVE_URL, my artefact suddenly got a strange URL: http://192.168.1.33:8080/jobs/hello/https://ci.<mydomain.tld>/archive/hello/1/hello-20170922.

I'm accessing Laminar via HTTP because I cannot proxy websockets with my lighttpd server - it lacks mod_websocket to do it, and Laminar is trying to access unsecured socket anyway - but the reason is not important as different URL schemes probably are.

strange behaviour of limits

I have noticed following:

I have couple of jobs queued and there are already let's say 4 jobs running. If I edit cfg/nodes/TAG.conf while jobs running, after I save laminar will launch another 4 jobs.

It should check if the limit of jobs is not already running and launch jobs only if the current running jobs < jobs defined in .conf

display or load more jobs when scrolling down on the /jobs/ page

So currently if you stay on the jobs page and let jobs run, you are able to see all jobs that started after you have opened the jobs page. If you follow a link to details about single job and come back you only see approx 30 jobs.

It would be nice if you scroll to the bottom of the page that the page would dynamically load more finished jobs (it can be 30 at a time).

Do you know what I am trying to say?

laminard crashing in hardened gentoo with: terminate called after throwing an instance of 'kj::ExceptionImpl'

Hi Oliver,

it is me again.

I am getting this on my box, again:

terminate called after throwing an instance of 'kj::ExceptionImpl'
  what():  kj/async-io-unix.c++:297: disconnected: ::read(fd, buffer, maxBytes): Connection reset by peer
stack: 0x7f7ca9133236 0x7f7ca91093f4 0x4456c0 0x42fb0c 0x7f7ca911076d 0x7f7ca9108ea9 0x7f7ca910ceb4 0x4338ba 0x42c08c 0x458274 0x42a157 0x7f7ca79e672c 0x42a368

What info do you need to debug?

Configuration reload before job run

Hi,
it would be nice if job/node (at least job) config was parsed before job run (trigger event) - in more complex scenarios with nodes, there is problem with jobs queued forever.
Example: Create job hello2.run and it's config hello2.conf, then execute laminarc trigger hello2 - job si queued forever. (no hello2.conf parsed until daemon restart).

By studying sources, I didn't found any simple workaround - should I create patch/pullrequest? I'd appraise you to handle this simple fix by yourself - I won't like to mess your clean code by my hand :-D

Internal refactor

  • Consider whether boost::filesystem and websocketpp can be replaced with new functionality in capnproto
  • Investigate suitability of capnproto http features for serving files (see #37)
  • Replace manual SIGCHLD handling with the new functionality from capnproto
  • Much tighter code could be written by relaxing the strict separation between capnp code as used in Server.cpp as compared to other files. It already leaked into Run in a few recent commits.
  • Reduce duplication in client.cpp and RpcImpl

Make jobs next run number immutable to crash

Hi Oliver,

so I have laminar crashing upon me under load. And if I restart it there are stale run directories, which don't allow to start new runs or jobs.

It would be good to solve the crashing problem of course, but also if a crash happens enable laminar to recover from it:

  • deleting stale directories in ~laminar/run/job_name/
    or
  • mark the last run number in the database so the new jobs get the next higher run number

Let me know what you think.

Pavol

laminard has executable stack

When packaging Laminar, I got this warning from rpmlint:

laminar.x86_64: W: executable-stack /usr/sbin/laminard
The binary declares the stack as executable.  Executable stack is usually an
error as it is only needed if the code contains GCC trampolines or similar
constructs which uses code on the stack.  One common source for needlessly
executable stack cases are object files built from assembler files which don't
define a proper .note.GNU-stack section.

That’s a CVE waiting to happen, so it should be fixed.

LAMINAR_KEEP_WORKDIR has no effect

When I configure the environment variable LAMINAR_KEEP_WORKDIR, the directories of the individual job runs are not preserved.

Steps to reproduce

  • Run as laminar user:
    $ LAMINAR_BIND_HTTP=unix:/var/lib/laminar/laminard.sock LAMINAR_KEEP_WORKDIR=1 /usr/bin/laminard
  • Trigger any job using laminarc

Expected results
The directory run/my-job/1/ is visible after the job crashed or finished.

Actual results
The directory run/my-job/1/ is temporarily visible. As soon as the job execution stops, the directory is removed.

BTW: I do like the project idea very much! Despite being a very young project, I chose to work with Laminar, because everything looks so tidy and polished :) Thanks for your efforts.

Build fails at several points

Tried to compile on Gentoo on my Raspberry Pi. Got this instead:

/home/kisik21/laminar/src/laminar.cpp: In member function ‘void Laminar::runFinished(Run*)’:
/home/kisik21/laminar/src/laminar.cpp:689:48: error: invalid conversion from ‘size_t* {aka unsigned int*}’ to ‘uLongf* {aka long unsigned int*}’ [-fpermissive]
             (unsigned char*)&r->log[0], logsize) == Z_OK) {
                                                ^

additionally, I had to install rapidjson for build to process, it happens to be included somewhere.

Running bash over ssh with different results from local and remote run

I am trying to execute a script over ssh, but get different results when compared to starting a local script.

Executing a script on the remote machine:

This is the pkg-builder-remote.run file on laminar server

#!/bin/bash
echo Running on robor ...
ssh [email protected] /bin/bash /root/test.sh
echo Done

And this is the test.sh file on the remote server:

#!/bin/bash
C_NAME=pkg-builder-1
echo $C_NAME
lxc launch -e -p prf-funtoo -p default fun-generic "$C_NAME"
sleep 3
lxc exec "$C_NAME" ip a add 10.214.101.2/24 dev eth0
lxc exec "$C_NAME" -- ping -c3 10.214.101.1
echo "Waiting 3 seconds"
sleep 3
lxc exec "$C_NAME" -- poweroff

Results from the run as displayed on laminar:
pkg-builder-remote #1

Console output

[laminar] Executing /var/lib/laminar/cfg/jobs/pkg-builder-remote.run
Running on robor ...
pkg-builder-1
Creating pkg-builder-1


Starting pkg-builder-1
PING 10.214.101.1 (10.214.101.1) 56(84) bytes of data.
64 bytes from 10.214.101.1: icmp_seq=1 ttl=64 time=0.152 ms
64 bytes from 10.214.101.1: icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from 10.214.101.1: icmp_seq=3 ttl=64 time=0.054 ms

--- 10.214.101.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2118ms
rtt min/avg/max/mdev = 0.054/0.087/0.152/0.046 ms
Waiting 3 seconds
Done

Executing the script over ssh connection

This is the pkg-builder.run file on laminar server:

#!/bin/bash
C_NAME=pkg-builder-$RUN

echo Connecting to remote host and starting container $C_NAME
ssh [email protected] "env C_NAME=$C_NAME /bin/bash -xe"<<"EOF"
        echo $C_NAME
        lxc launch -e -p prf-funtoo -p default fun-generic "$C_NAME"
        sleep 3
        lxc exec "$C_NAME" ip a add 10.214.101.2/24 dev eth0
        lxc exec "$C_NAME" -- ping -c3 10.214.101.1
        echo "Waiting 3 seconds"
        sleep 3
        lxc exec "$C_NAME" -- poweroff
EOF

This is the output from laminar:

Console output

[laminar] Executing /var/lib/laminar/cfg/jobs/pkg-builder.run
We are going to start container:
Connecting to remote host and starting container pkg-builder-37
+ lxc launch -e -p prf-funtoo -p default fun-generic pkg-builder-37
Creating pkg-builder-37


Starting pkg-builder-37
+ sleep 3
+ lxc exec pkg-builder-37 ip a add 10.214.101.2/24 dev eth0

So the ping command and sleep and poweroff commands never get executed.

Am I doing something wrong?

Thanks

add new graphs to the home page?

  • It would be nice to spot which jobs suffered regression or recovered, but that might be too specific to my use-case. So like last failed job where previous job succeeded or vice versa show jobs that failed before but are ok after last run.
  • pass rate of the package/job sorted
  • how many jobs from a group failed%.
  • show jobs that are taking longer/shorter then before (significantly)
  • show average job run

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.