rci/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! rci is wrapper for environment variables of some common continiuous integration services.
//! At the moment [travis](https://travis-ci.org/) and [circle-ci](https://circleci.com/) is supported.
//! A possible use case for this library is to check if your tests are running in an contniuous
//! service.
//! **Don't** use this to skip all of your tests and pretend everything works fine!
//! If you are testing for example audio or graphics output
//! that is not available in certain CI environments
//! then you can use this library to skip those tests,
//! like shown in the following example:
//!
//! ```rust
//! use rci::*;
//!
//! let ci = Ci::new();
//! if ci.is_none() {
//! return;
//! } else {
//! println!("I'm running in: {}", ci.unwrap());
//! }
//! ```
use std::env;
use std::fmt;
#[derive(PartialEq, Debug)]
pub enum CiService {
Travis,
Circle,
Unknown,
}
macro_rules! err {
($expr:expr) => {
match $expr {
Ok(val) => Some(val),
Err(e) => match e {
::std::env::VarError::NotPresent => None,
_ => panic!(e),
}
}
}
}
macro_rules! lang_version {
($lang:expr, $name:ident) => {
/// **Travis only**: Returns the version of the language that is used.
pub fn $name(&self) -> Option<String> {
match self.service {
CiService::Travis => err!(env::var(format!("TRAVIS_{}_VERSION", $lang))),
_ => None,
}
}
}
}
pub struct Ci {
service: CiService,
}
impl Ci {
pub fn new() -> Option<Self> {
let s = Ci::which_ci();
match s {
CiService::Travis | CiService::Circle => Some(Ci { service: s }),
_ => None,
}
}
pub fn which_ci() -> CiService {
match (err!(env::var("TRAVIS")), err!(env::var("CIRCLECI"))) {
(Some(_), None) => CiService::Travis,
(None, Some(_)) => CiService::Circle,
_ => CiService::Unknown,
}
}
/// Returns the locale setting, g.e. `en_US.UTF-8`.
pub fn lang() -> Option<String> {
err!(env::var("LANG"))
}
/// Returns the search path.
pub fn path() -> Option<String> {
err!(env::var("PATH"))
}
/// Returns the path to the users home directory.
pub fn home() -> Option<String> {
err!(env::var("HOME"))
}
pub fn is_travis(&self) -> bool {
match self.service {
CiService::Travis => true,
_ => false,
}
}
pub fn is_circle(&self) -> bool {
match self.service {
CiService::Circle => true,
_ => false,
}
}
pub fn branch(&self) -> Option<String> {
match self.service {
CiService::Circle => err!(env::var("CIRCLE_BRANCH")),
CiService::Travis => err!(env::var("TRAVIS_BRANCH")),
_ => None,
}
}
/// **Circle only**
/// A permanent link to the current build, for example,
/// https://circleci.com/gh/circleci/frontend/933
pub fn build_url(&self) -> Option<String> {
match self.service {
CiService::Circle => err!(env::var("CIRCLE_BUILD_URL")),
_ => None,
}
}
/// Returns the build number.
/// TODO: convert this to a number.
pub fn build_id(&self) -> Option<String> {
match self.service {
CiService::Circle => err!(env::var("CIRCLE_BUILD_NUM")),
CiService::Travis => err!(env::var("TRAVIS_BUILD_NUMBER")),
_ => None,
}
}
/// **Travis only**: The absolute path to the directory where the repository
/// being built has been copied on the worker.
/// TODO: Return a filesystem path instead?
pub fn build_dir(&self) -> Option<String> {
match self.service {
CiService::Travis => err!(env::var("TRAVIS_BUILD_DIR")),
_ => None,
}
}
/// The sha1 hash of the commit being tested.
pub fn commit(&self) -> Option<String> {
match self.service {
CiService::Circle => err!(env::var("CIRCLE_SHA1")),
CiService::Travis => err!(env::var("TRAVIS_COMMIT")),
_ => None,
}
}
/// The number of the pull request this build forms part of.
/// If this build is not part of a pull request, `None` is returned.
/// TODO: convert this to a number.
pub fn pull_request(&self) -> Option<String> {
match self.service {
CiService::Circle => err!(env::var("CIRCLE_PR_NUMBER")),
CiService::Travis => {
let pr = err!(env::var("TRAVIS_PULL_REQUEST")).unwrap_or("false".to_string());
if pr == "false" {
None
} else {
Some(pr)
}
}
_ => None,
}
}
lang_version!("DART", dart);
lang_version!("GO", go);
lang_version!("HAXE", haxe);
lang_version!("JDK", java);
lang_version!("JULIA", julia);
lang_version!("NODE", node);
lang_version!("OTP", otp);
lang_version!("PERL", perl);
lang_version!("PHP", php);
lang_version!("PYTHON", python);
lang_version!("R", r);
lang_version!("RUBY", ruby);
lang_version!("RUST", rust);
lang_version!("SCALA", scala);
}
impl fmt::Display for Ci {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Continuous Integration Service: {:?}", self.service)
}
}