Skip to content

Commit

Permalink
feat: add screwdriver.cd support. (#278)
Browse files Browse the repository at this point in the history
Co-authored-by: Enrique Mora Parraga <enrique.mora.parraga@yahooinc.com>
  • Loading branch information
quike and Enrique Mora Parraga authored Apr 29, 2023
1 parent eab0512 commit 3a9520f
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 19 deletions.
71 changes: 52 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ if (isCI) {

**Note**: Some variables can be detected only on certain CI services. See [Supported CI](#supported-ci).

**Note**: The `pr` and `prBranch` properties are only available for builds triggered when a Pull Request is opened/updated and not on builds triggered by a push on a branch even if that branch happens to be the branch from which the Pull Request originated.
**Note**: The `pr` and `prBranch` properties are only available for builds triggered when a Pull Request is
opened/updated and not on builds triggered by a push on a branch even if that branch happens to be the branch from which
the Pull Request originated.

## Supported CI

Expand All @@ -101,6 +103,7 @@ if (isCI) {
| [Netlify](https://docs.netlify.com/configure-builds/environment-variables/#netlify-configuration-variables) | `netlify` | :white_check_mark: | [:warning:](#netlify) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| [Puppet](https://puppet.com/docs/pipelines-for-apps/enterprise/environment-variable.html) | `puppet` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: |
| [Sail CI](https://sail.ci/docs/environment-variables) | `sail` | :white_check_mark: | [:warning:](#sail) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: |
| [Screwdriver.cd](https://docs.screwdriver.cd/user-guide/environment-variables) | `screwdriver` | :white_check_mark: | [:warning:](#screwdriver) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| [Scrutinizer](https://scrutinizer-ci.com/docs/build/environment-variables) | `scrutinizer` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: |
| [Semaphore](https://docs.semaphoreci.com/article/12-environment-variables) | `semaphore` | :white_check_mark: | [:warning:](#semaphore) | :white_check_mark: | [:warning:](#semaphore) | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| [Shippable](http://docs.shippable.com/ci/env-vars/#stdEnv) | `shippable` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Expand All @@ -114,9 +117,11 @@ if (isCI) {

:warning: See [Caveats](#caveats)

**Note**: Unsupported properties will always be `undefined`. For example if a Ci services doesn't support triggering builds when a Pull Request is opened/updated, `isPr` will be `undefined`.
**Note**: Unsupported properties will always be `undefined`. For example if a Ci services doesn't support triggering
builds when a Pull Request is opened/updated, `isPr` will be `undefined`.

**Note**: If none of the above CI services is detected, `commit` and `branch` are determined based on the local Git repository, and `isCi` is determined based on the `CI` environment variable.
**Note**: If none of the above CI services is detected, `commit` and `branch` are determined based on the local Git
repository, and `isCi` is determined based on the `CI` environment variable.

## API

Expand All @@ -138,7 +143,8 @@ The object to read environment variables from.
Type: `String`<br>
Default: `process.cwd()`

The current working directory in which to execute `git` commands used to determine the `commit` and `branch` [Result](#result) properties in case no [supported CI](#supported-ci) is detected.
The current working directory in which to execute `git` commands used to determine the `commit`
and `branch` [Result](#result) properties in case no [supported CI](#supported-ci) is detected.

### Result

Expand All @@ -150,48 +156,75 @@ Type: `Object`

### AWS CodeBuild

AWS CodeBuild doesn't provide an environment variable to determine the current Git branch being built. In addition, it clones the repository in a [detached head state](https://git-scm.com/docs/git-checkout#_detached_head) so the branch cannot be determined with `git rev-parse --abbrev-ref HEAD`.
To work around this limitation, `env-ci` look for the remote branches having the same `HEAD` as the local detached `HEAD` to determine the branch from which the detached `HEAD` was created.
In the rare case where there is multiple remote branches with the same `HEAD` as the local detached `HEAD`, `env-ci` will arbitrarily pick the first one. This can lead to an inaccurate `branch` value in such circumstances.
AWS CodeBuild doesn't provide an environment variable to determine the current Git branch being built. In addition, it
clones the repository in a [detached head state](https://git-scm.com/docs/git-checkout#_detached_head) so the branch
cannot be determined with `git rev-parse --abbrev-ref HEAD`.
To work around this limitation, `env-ci` look for the remote branches having the same `HEAD` as the local
detached `HEAD` to determine the branch from which the detached `HEAD` was created.
In the rare case where there is multiple remote branches with the same `HEAD` as the local detached `HEAD`, `env-ci`
will arbitrarily pick the first one. This can lead to an inaccurate `branch` value in such circumstances.

### Buddy

For builds triggered when [a Pull Request is opened/updated](https://buddy.works/knowledge/deployments/pull-requests), Buddy doesn't provide an environment variable indicating the branch from which the Pull Request originated nor the target branch. It also build from a branch named `pull/<PR number>` so the target branch cannot be determined with a `git` command.
Therefore in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` and `prBranch` properties.
For builds triggered when [a Pull Request is opened/updated](https://buddy.works/knowledge/deployments/pull-requests),
Buddy doesn't provide an environment variable indicating the branch from which the Pull Request originated nor the
target branch. It also build from a branch named `pull/<PR number>` so the target branch cannot be determined with
a `git` command.
Therefore, in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` and `prBranch`
properties.

See [feature request](https://forum.buddy.works/t/determine-pull-request-branch-with-environment-variable/911).

### CircleCI

For builds triggered when a Pull Request is opened/updated, CircleCI doesn't provide an environment variable indicating the target branch.
Therefore in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property. However `prBranch` will be set.
For builds triggered when a Pull Request is opened/updated, CircleCI doesn't provide an environment variable indicating
the target branch.
Therefore, in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property.
However `prBranch` will be set.

See [feature request](https://discuss.circleci.com/t/create-a-circle-target-branch-envar/10022).

### Cloudflare Pages

For builds triggered when a Pull Request is opened/updated, Cloudflare Pages will re-use the branch variable for the originating branch and not provide a target. Therefore `env-ci` will not be able to determine the `prBranch` property however `branch` will always be set.
For builds triggered when a Pull Request is opened/updated, Cloudflare Pages will re-use the branch variable for the
originating branch and not provide a target. Therefore `env-ci` will not be able to determine the `prBranch` property
however `branch` will always be set.

### Jenkins

Triggering build when a Pull Request is opened/updated is supported only via the [ghprb-plugin](https://github.com/jenkinsci/ghprb-plugin) and [gitlab-plugin](https://github.com/jenkinsci/gitlab-plugin). Therefore `env-ci` will set `isPr`, `pr` and `prBranch` and define `branch` with the Pull Request target branch only if one those plugin is used.
Triggering build when a Pull Request is opened/updated is supported only via
the [ghprb-plugin](https://github.com/jenkinsci/ghprb-plugin)
and [gitlab-plugin](https://github.com/jenkinsci/gitlab-plugin). Therefore `env-ci` will set `isPr`, `pr` and `prBranch`
and define `branch` with the Pull Request target branch only if one those plugin is used.

### Netlify

For builds triggered when a Pull Request is opened/updated, Netlify doesn't provide an environment variable indicating the target branch.
Therefore in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property. However `prBranch` will be set.
For builds triggered when a Pull Request is opened/updated, Netlify doesn't provide an environment variable indicating
the target branch.
Therefore, in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property.
However `prBranch` will be set.

See [feature request](https://answers.netlify.com/t/access-pr-target-branch-when-deploying-preview-build/32402)

### Sail

For builds triggered when a Pull Request is opened/updated, Sail doesn't provide an environment variable indicating the target branch, and the one for the current branch is set to `pull/<PR number>` independently of the the branch name from which the Pull Request originated.
Therefore in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` and `prBranch` properties.
For builds triggered when a Pull Request is opened/updated, Sail doesn't provide an environment variable indicating the
target branch, and the one for the current branch is set to `pull/<PR number>` independently of the the branch name from
which the Pull Request originated.
Therefore, in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` and `prBranch`
properties.

### Semaphore

For builds triggered when a Pull Request is opened/updated, Semaphore 1.0 doesn't provide an environment variable indicating the target branch.
Therefore in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property. However `prBranch` will be set.
For builds triggered when a Pull Request is opened/updated, Semaphore 1.0 doesn't provide an environment variable
indicating the target branch.
Therefore, in the case of Pull Request builds, `env-ci` will not be able to determine the `branch` property.
However `prBranch` will be set.
On Semaphore 2.0 the `branch` and `prBranch` properties will work as expected.

The property `tag` is only available on Semaphore 2.0.

### Screwdriver

For builds triggered when a Pull Request is opened/updated, Screwdriver sets the `env.GIT_BRANCH` as `head:pr` branch
type (Example:`origin/refs/pull/1/head:pr`) while at commit level (non PR) it does set it with the actual branch (Example: `origin/main`).
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import jenkins from "./services/jenkins.js";
import netlify from "./services/netlify.js";
import puppet from "./services/puppet.js";
import sail from "./services/sail.js";
import screwdriver from "./services/screwdriver.js";
import scrutinizer from "./services/scrutinizer.js";
import semaphore from "./services/semaphore.js";
import shippable from "./services/shippable.js";
Expand Down Expand Up @@ -50,6 +51,7 @@ const services = {
netlify,
puppet,
sail,
screwdriver,
scrutinizer,
semaphore,
shippable,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"netlify",
"puppet",
"sail",
"screwdriver",
"scrutinizer",
"semaphore",
"shippable",
Expand Down
26 changes: 26 additions & 0 deletions services/screwdriver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// https://docs.screwdriver.cd/user-guide/environment-variables

export default {
detect({ env }) {
return Boolean(env.SCREWDRIVER);
},
configuration({ env }) {
const pr = env.SD_PULL_REQUEST;
const isPr = Boolean(pr);

return {
name: "Screwdriver.cd",
service: "screwdriver",
branch: isPr ? env.PR_BASE_BRANCH_NAME : env.GIT_BRANCH,
prBranch: isPr ? env.PR_BRANCH_NAME : undefined,
commit: env.SD_BUILD_SHA,
build: env.SD_BUILD_ID,
buildUrl: env.SD_UI_BUILD_URL,
job: env.SD_JOB_ID,
pr,
isPr,
slug: env.SD_PIPELINE_NAME,
root: env.SD_ROOT_DIR,
};
},
};
7 changes: 7 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ test("Sail CI", (t) => {
t.is(service, "sail");
});

test("Screwdriver.cd", (t) => {
const { isCi, service } = envCi({ env: { SCREWDRIVER: "true" } });

t.is(isCi, true);
t.is(service, "screwdriver");
});

test("Scrutinizer", (t) => {
const { isCi, service } = envCi({ env: { SCRUTINIZER: "true" } });

Expand Down
74 changes: 74 additions & 0 deletions test/services/screwdriver.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import test from "ava";
import screwdriver from "../../services/screwdriver.js";

const env = {
SCREWDRIVER: "true",
SD_BUILD_SHA: "b5a94cdabf23b21303a0e6d5be5e96bd6300847a",
SD_PROJECT: "259",
SD_BUILD_ID: "173",
SD_EVENT_ID: "1",
SD_JOB_ID: "123",
SD_PIPELINE_NAME: "d2lam/myPipeline",
SCM_URL: "https://github.com/d2lam/myPipeline",
GIT_URL: "https://github.com/d2lam/myPipeline.git",
GIT_BRANCH: "my-branch",
SD_ROOT_DIR: "sd/workspace",
SD_SOURCE_DIR: "sd/workspace/src/github.com/d2lam/myPipeline",
};

test("Push", (t) => {
t.deepEqual(
screwdriver.configuration({
env: {
...env,
SD_EVENT_ID: "pipeline",
GIT_BRANCH: "origin/main",
SD_UI_BUILD_URL: `https://cd.screwdriver.cd/pipelines/${env.SD_PROJECT}/builds/${env.SD_BUILD_ID}`,
},
}),
{
name: "Screwdriver.cd",
service: "screwdriver",
commit: "b5a94cdabf23b21303a0e6d5be5e96bd6300847a",
build: "173",
buildUrl: "https://cd.screwdriver.cd/pipelines/259/builds/173",
job: "123",
branch: "origin/main",
prBranch: undefined,
pr: undefined,
isPr: false,
slug: "d2lam/myPipeline",
root: "sd/workspace",
}
);
});

test("PR", (t) => {
t.deepEqual(
screwdriver.configuration({
env: {
...env,
SD_PULL_REQUEST: "1",
SD_EVENT_ID: "pr",
PR_BASE_BRANCH_NAME: "main",
PR_BRANCH_NAME: "origin/feat/env-ci",
GIT_BRANCH: "origin/refs/pull/1/head:pr",
SD_UI_BUILD_URL: `https://cd.screwdriver.cd/pipelines/${env.SD_PROJECT}/builds/${env.SD_BUILD_ID}`,
},
}),
{
name: "Screwdriver.cd",
service: "screwdriver",
commit: "b5a94cdabf23b21303a0e6d5be5e96bd6300847a",
build: "173",
buildUrl: "https://cd.screwdriver.cd/pipelines/259/builds/173",
job: "123",
branch: "main",
prBranch: "origin/feat/env-ci",
pr: "1",
isPr: true,
slug: "d2lam/myPipeline",
root: "sd/workspace",
}
);
});

0 comments on commit 3a9520f

Please sign in to comment.