Skip to content

LoganBarnett/jj

Repository files navigation

Jenkins Job runner

jj is a command line Jenkins job runner. It requires a lightweight configuration.

Why not jenkins-cli?

The jenkins-cli utility (docs) does much of what jj does, but it isn’t easy to create configurations that are both secure and easy shortcuts. jj strives to be a better mechanism in which to kick off and watch jobs as well.

A short list of ways in which jj differs from jenkins-cli:

  1. Authentication can be made secure (via pass or environment variables).
  2. Servers are easy to reference to reduce invocation complexity at the command line.
  3. Jobs themselves are also easy to reference to reduce command line invocation complexity.
  4. Jobs can be watched (coming soon!) - new builds on a job are automatically displayed in a persistent run. A sort of tail -f for a job.
  5. Child jobs can similarly be configured to watch (coming soon!).
  6. jj can be used for similar job invocation / watching on non-Jenkins systems (Concourse, GitHub Actions, etc). Also coming soon!

usage

running with configuration

The utility structure is one of:

jj <job name> [-s/--server <server-name>] [-v...]

Omitting [--server] will require jj to find the defaultServer in ~/.config/jj/config.toml. The value of defaultServer must correspond to a TOML section, which represents the server to be contacted.

Much like ssh, use -v to increase verbosity in the logging, with subsequent v’s increasing the verbosity further (such as -vv and -vvv). Beware that at TRACE the API token is logged!

default_server = "foo"

[foo]
host_url = "http://jenkins.foo:8080"
username = "jeeves"
token_eval = "printf '%s' 'totally secure token'"

[secure]
host_url = "https://jenkins.foo"
username = "jeeves"
token_eval = "pass jenkins-foo-api-token"

running without configuration

Coming soon!

When running without a configuration file, the notion of a default_server isn’t as strong.

jobs with parameters

Simply use --param foo=bar or -P foo=bar (add more --params / -P uses for additional parameters) to provide parameters to the build. Otherwise its defaults will be assumed for all missing parameters.

jobs with approval gates

Coming soon!

verbosity

jj can print log messages using -v and adding more v’s will increase verbosity further like it does for ssh. So for the second level of verbosity, use -vv, the third -vvv, and so on.

Beware that at -vvvv, jj will print your API token! This is considered helpful in the even that your token_eval is having trouble and you need to see the output of it.

All logging goes to stderr so you can be verbose and continue do any processing of the job output (going to stdout) without any changes.

contributing

principles

configuration files for convenience, not necessity

The configuration file is to optimize common, manual usage of the program. The configuration file should not be required to perform execution, so long as all of the arguments necessary are provided.

documentation first

Documentation comes first. A feature is not done (and arguably not started) until there is documentation of both its intent and usage.

integration tests instead of unit tests

Unit tests inevitably require mocks, which are lies. In all practicality we must eventually mock something, but the internals of the application are not necessary to mock. Our tests all share the entry point of the program itself, and do not exercise some tiny portion of the program with the hopes that the mocks replicate the correct behavior.

100% test coverage

If functionality cannot be covered with a test, then the functionality is doomed to regress from future changes. All functionality must have 100% test coverage.

It’s okay to fall short

We will attempt to make contributions welcome, even if they do not follow the above principles. That being said, expect adjustments or requests to the contributions to bring it into alignment with the above principles.

design

architecture

This repository follows the same convention as Go’s cmd/ pattern: the library crate is the product and the binary crate is the frontend. The library owns all domain logic — external service communication, business rules, data types, and error types — including any I/O that is intrinsic to the domain (HTTP calls, database access, file reads, and so on). The binary’s sole responsibilities are parsing arguments, reading configuration files, initialising logging, writing to stdout/stderr, and returning exit codes.

The formal name for this is the library-first design, related to Hexagonal Architecture’s notion of ports and adapters. That pattern would go further and abstract all I/O behind traits, allowing transports to be swapped out. We deliberately stop short of that: the external interactions this library performs are the domain, not infrastructure to be abstracted away. There is nothing meaningful to inject.

The practical test: if another team wanted to embed this functionality in their own tool, they should be able to import the library crate directly without touching the binary crate.

operational flow

About

Run a Jenkins job from the command line.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors