This project provides a tool for exercising participating projects with a pinned bleeding-edge ClojureScript compiler version. The goal is to have some smoke tests which allow us to detect issues early before releasing a new ClojureScript version.
If you are using Travis for CI, participating in Canary builds involves a few simple steps. (Before doing this, ask someone in the cljs-oss organization for commit rights.)
-
Revise your
.travis.ymlto fetch the Canary-built ClojureScript JAR.before_install: - curl -sSL https://raw.githubusercontent.com/cljs-oss/canary/master/scripts/install-canary.sh | bash -
Configure your project's build so that it honors the
CANARY_CLOJURESCRIPT_VERSIONenvironment variable. If using Leiningen, this can be accomplished by revising your ClojureScript dependency inproject.cljto look like:[org.clojure/clojurescript ~(or (System/getenv "CANARY_CLOJURESCRIPT_VERSION") "1.9.946")] -
Obtain Travis Access token:
Probably the easiest way is to copy it from your Travis UI web interface (look under
Settings/Settings/API authentication).Note that an alternative way to obtain a Travis Access token is by doing
gem install travis && travis login && travis token. See their api reference for updated info on how to retrieve access tokens. -
Set up Canary with a Travis access token. Replace
YOUR_PROJECTwith the name of your project anddeadbeefbelow with your Travis Token obtained above.git clone --branch jobs [email protected]:cljs-oss/canary.git cd canary travis encrypt CANARY_YOUR_PROJECT_TRAVIS_TOKEN=deadbeef --add env.global git add .travis.yml git commit -m "add CANARY_YOUR_PROJECT_TRAVIS_TOKEN [ci skip]" git push origin jobsWarning: Please make sure that you run
travis encryptinside your canary checkout of the jobs branch as shown above. Running it outside seems to produce some encrypted value, but the result is corrupted when actually used by travis. -
Add a Canary task to trigger CI builds of your project. This is done by adding a
^:taskto a namespace in themasterbranch underrunner/src/canary/projects, like this (replacinggithub-yourname,your-projectandYOUR_PROJECT):(ns canary.projects.github-yourname (:require [canary.runner.travis :as travis])) (defn ^:task your-project [options] (travis/request-build! "github-yourname/your-project" "CANARY_YOUR_PROJECT_TRAVIS_TOKEN" options))
After setting this up, you can force an out-of-cycle test of your job going into the jobs branch and making a commit like this (replacing your-project) and pushing it:
git commit --allow-empty -m "job --only your-project"
Canary provides a script which can be used to run a job. Each job is assigned a ClojureScript compiler version. It builds compiler jar, uploads it and then runs exercises of individual projects in parallel (we call them tasks). Finally it waits for task results and generates a report for archiving.
Typically you don't run canary script on your local machine but rather invoke it on some machine in the cloud. For your convenience a new job can be triggered by committing an empty commit into the jobs branch. Travis machine will then execute canary script possibly triggering more child Travis builds for individual project tasks. At the end, results are generated and archived in the results branch. Also look into GitHub releases of this repo where individual built compiler versions get published.
./scripts/docker-build.sh
./scripts/docker-run.sh help
./scripts/docker-run.sh list
./scripts/docker-run.sh job
./scripts/docker-clean.sh # to start from scratch./runner/run.sh job -v -r master
./scripts/blow-local-caches.sh # to start from scratch- the script is called
runner - ClojureScript compiler is usually simply referred to as the
compiler - a list of relevant projects/libraries is called
projects - a single request for a complete round of tests is called a
job - a single project test is called a
task
Instead of maintaining multiple git repos, let's have just a single mono-repo canary with following branches:
masterwhere the source code for therunnerlivesjobswhere anyone with commit rights can trigger a newjob(as a new commit)resultswhere therunnerwill produce one commit perjob
All participating project authors will get commit access to this repo and can collaborate on the master branch.
When a job is triggered. The runner goes through following steps:
- prepares
compiler's jar according to requested parameters (repo/version) - determines which
tasksshould be part of thejobbased on request parameters - spawns all
tasks(in parallel) instructing them to use thecompiler - waits for
tasksresults and collects them - generates a report and commits it in the
resultsbranch
The runner is implemented in Clojure for convenience. Each project author gets own place (function/script)
for implementing functionality specific for their project. Authors are expected to trigger test builds on their own repos
(e.g. via Travis) and simply collect results back. But anyone can use an escape hatch to invoke a shell script or do whatever
they need in Clojure. For example cloning their repo and running tests directly in the context of the runner.
We wrap runner in a Docker container to provide well-controlled environment for tasks (possibly shell scripts).
We are developers and we have git and GitHub which is a great publishing platform on its own. Travis alone will provide some trace
of a job (depending on what runner script and individual tasks output to stdout). But ultimately a commit into results
branch presents all interesting results also for archivation purposes. Then anyone can use their git-fu to follow those or
process them further.
Please read the readme in the jobs branch with details on that.
No problem. You can point Canary to your own fork of ClojureScript by specifying --compiler-repo and --compiler-rev parameters.
You will need to write a new task for your project. First look how existing projects are implemented. Ask for commit access. You can write your task as a Clojure function or as a shell script.
In case of a Clojure function you have to annotate it with ^:task metadata so that runner recognizes it. In general
you can do whatever you need to do in your task (you can block, it is running on a separate thread) - this will depend on your project setup.
To ease some common scenarios we provide some helper functions. For example canary.runner.travis namespace might be very useful for triggering
a Travis build for your own project.
In case of a shell script. You simply create your_name.sh in the projects directory. Script has to return with zero exit
code to be considered as passing. Standard outputs will be embedded into the final report, so don't be too verbose there.
You can test your task locally. Running jobs without --production flag should do no harm. When using travis/request-build!
it will mock it by default. You will have to add --production as the last step for fine-tuning final version of the code.
For inspiration here
is the task for cljs-devtools, and here
is the adaptation needed in the project itself. Please note that child Travis build triggered by travis/request-build!
is configured with bunch of extra env variables prefixed with CANARY_ - those have to be taken into account by
the participating project (an example here).
Also for us to be able to trigger builds of your Travis projects you will also have to provide a Travis
API token for triggering the builds on your behalf.
You should encrypt your token and commit it into .travis.yml in jobs branch (replace YOUR_PROJECT and deadbeef):
git clone --branch jobs [email protected]:cljs-oss/canary.git
cd canary
travis encrypt CANARY_YOUR_PROJECT_TRAVIS_TOKEN=deadbeef --add env.global
git add .travis.yml
git commit -m "add CANARY_YOUR_PROJECT_TRAVIS_TOKEN [ci skip]"
git push origin jobs
You are on your own. We haven't implemented similar helpers as for Travis yet. Want to contribute them? That would be great.
Inspired by ideas of @deraen and @mfikes.
You might discuss this in #cljs-dev channel on clojurians.net Slack.