diff --git a/packages/server/__snapshots__/record_spec.coffee b/packages/server/__snapshots__/record_spec.coffee new file mode 100644 index 0000000000..218584584e --- /dev/null +++ b/packages/server/__snapshots__/record_spec.coffee @@ -0,0 +1,57 @@ +exports['lib/modes/record .generateProjectBuildId calls api.createRun with args 1'] = [ + { + "projectId": "id-123", + "recordKey": "key-123", + "commitSha": "sha-123", + "commitBranch": "master", + "commitAuthorName": "brian", + "commitAuthorEmail": "brian@cypress.io", + "commitMessage": "such hax", + "remoteOrigin": "https://github.com/foo/bar.git", + "ciParams": { + "foo": "bar" + }, + "ciProvider": "circle", + "ciBuildNumber": "build-123", + "groupId": null + } +] + +exports['lib/modes/record .generateProjectBuildId passes groupId 1'] = [ + { + "projectId": "id-123", + "recordKey": "key-123", + "commitSha": "sha-123", + "commitBranch": "master", + "commitAuthorName": "brian", + "commitAuthorEmail": "brian@cypress.io", + "commitMessage": "such hax", + "remoteOrigin": "https://github.com/foo/bar.git", + "ciParams": { + "foo": "bar" + }, + "ciProvider": "circle", + "ciBuildNumber": "build-123", + "groupId": "gr123" + } +] + +exports['lib/modes/record .generateProjectBuildId figures out groupId from CI environment variables 1'] = [ + { + "projectId": "id-123", + "recordKey": "key-123", + "commitSha": "sha-123", + "commitBranch": "master", + "commitAuthorName": "brian", + "commitAuthorEmail": "brian@cypress.io", + "commitMessage": "such hax", + "remoteOrigin": "https://github.com/foo/bar.git", + "ciParams": { + "foo": "bar" + }, + "ciProvider": "circle", + "ciBuildNumber": "build-123", + "groupId": "ci-group-123" + } +] + diff --git a/packages/server/lib/api.coffee b/packages/server/lib/api.coffee index b661a154d2..7df353f60d 100644 --- a/packages/server/lib/api.coffee +++ b/packages/server/lib/api.coffee @@ -89,6 +89,20 @@ module.exports = { .catch(errors.StatusCodeError, formatResponseBody) createRun: (options = {}) -> + body = _.pick(options, [ + "projectId" + "recordKey" + "commitSha" + "commitBranch" + "commitAuthorName" + "commitAuthorEmail" + "commitMessage" + "remoteOrigin" + "ciParams" + "ciProvider" + "ciBuildNumber", + "groupId" + ]) rp.post({ url: Routes.runs() json: true @@ -96,19 +110,7 @@ module.exports = { headers: { "x-route-version": "2" } - body: _.pick(options, [ - "projectId" - "recordKey" - "commitSha" - "commitBranch" - "commitAuthorName" - "commitAuthorEmail" - "commitMessage" - "remoteOrigin" - "ciParams" - "ciProvider" - "ciBuildNumber" - ]) + body: body }) .promise() .get("buildId") diff --git a/packages/server/lib/modes/record.coffee b/packages/server/lib/modes/record.coffee index c751eb1a88..c4e197a69d 100644 --- a/packages/server/lib/modes/record.coffee +++ b/packages/server/lib/modes/record.coffee @@ -29,7 +29,7 @@ module.exports = { repo.getBranch() - generateProjectBuildId: (projectId, projectPath, projectName, recordKey) -> + generateProjectBuildId: (projectId, projectPath, projectName, recordKey, group, groupId) -> if not recordKey errors.throw("RECORD_KEY_MISSING") @@ -44,6 +44,11 @@ module.exports = { message: repo.getMessage() }) .then (git) -> + # only send groupId if group option is true + if group + groupId ?= ciProvider.groupId() + else + groupId = null api.createRun({ projectId: projectId recordKey: recordKey @@ -56,6 +61,7 @@ module.exports = { ciParams: ciProvider.params() ciProvider: ciProvider.name() ciBuildNumber: ciProvider.buildNum() + groupId: groupId }) .catch (err) -> switch err.statusCode @@ -218,7 +224,7 @@ module.exports = { .then (cfg) => {projectName} = cfg - @generateProjectBuildId(projectId, projectPath, projectName, options.key) + @generateProjectBuildId(projectId, projectPath, projectName, options.key, options.group, options.groupId) .then (buildId) => ## bail if we dont have a buildId return if not buildId diff --git a/packages/server/lib/util/args.coffee b/packages/server/lib/util/args.coffee index ed03dc7ff5..5b3677a849 100644 --- a/packages/server/lib/util/args.coffee +++ b/packages/server/lib/util/args.coffee @@ -5,7 +5,7 @@ coerce = require("./coerce") config = require("../config") cwd = require("../cwd") -whitelist = "appPath execPath apiKey smokeTest getKey generateKey cliVersion runProject project spec ci record updating ping key logs clearLogs returnPkg version mode autoOpen removeIds showHeadlessGui config exitWithCode hosts browser headless outputPath".split(" ") +whitelist = "appPath execPath apiKey smokeTest getKey generateKey cliVersion runProject project spec ci record updating ping key logs clearLogs returnPkg version mode autoOpen removeIds showHeadlessGui config exitWithCode hosts browser headless outputPath group groupId".split(" ") whitelist = whitelist.concat(config.getConfigKeys()) parseNestedValues = (vals) -> @@ -48,9 +48,10 @@ module.exports = { "env": "environmentVariables" "headless": "isTextTerminal" "show-headless-gui":"showHeadlessGui" - "exit-with-code": "exitWithCode" + "exit-with-code": "exitWithCode" "reporter-options": "reporterOptions" - "output-path": "outputPath" + "output-path": "outputPath" + "group-id": "groupId" } }) diff --git a/packages/server/lib/util/ci_provider.coffee b/packages/server/lib/util/ci_provider.coffee index bc3107d334..728258eb7f 100644 --- a/packages/server/lib/util/ci_provider.coffee +++ b/packages/server/lib/util/ci_provider.coffee @@ -37,6 +37,11 @@ buildNums = (provider) -> { travis: process.env.TRAVIS_BUILD_NUMBER }[provider] +groupIds = (provider) -> { + # for CircleCI v2 use workflow id to group builds + circle: process.env.CIRCLE_WORKFLOW_ID +}[provider] + params = (provider) -> { appveyor: { accountName: process.env.APPVEYOR_ACCOUNT_NAME @@ -122,4 +127,7 @@ module.exports = { buildNum: -> buildNums(getProviderName()) ? null + + groupId: -> + groupIds(getProviderName()) ? null } diff --git a/packages/server/test/integration/cypress_spec.coffee b/packages/server/test/integration/cypress_spec.coffee index 1cac52fe88..0cf8fc6f7d 100644 --- a/packages/server/test/integration/cypress_spec.coffee +++ b/packages/server/test/integration/cypress_spec.coffee @@ -767,7 +767,7 @@ describe "lib/cypress", -> beforeEach -> @setup = => - @createRun = @sandbox.stub(api, "createRun").withArgs({ + createRunArgs = { projectId: @projectId recordKey: "token-123" commitSha: "sha-123" @@ -779,7 +779,9 @@ describe "lib/cypress", -> ciProvider: "travis" ciBuildNumber: "987" ciParams: null - }) + groupId: null + } + @createRun = @sandbox.stub(api, "createRun").withArgs(createRunArgs) @upload = @sandbox.stub(record, "upload").resolves() @sandbox.stub(stdout, "capture").returns({ diff --git a/packages/server/test/unit/ci_provider_spec.coffee b/packages/server/test/unit/ci_provider_spec.coffee index 22a094d277..bbd37f2b44 100644 --- a/packages/server/test/unit/ci_provider_spec.coffee +++ b/packages/server/test/unit/ci_provider_spec.coffee @@ -17,6 +17,22 @@ describe "lib/util/ci_provider", -> ## restore the env process.env = JSON.parse(@env) + context "grou-id", -> + describe "circle", -> + beforeEach -> + process.env.CIRCLECI = true + process.env.CIRCLE_BUILD_URL = "circle build url" + process.env.CIRCLE_BUILD_NUM = "4" + + it "grabs workflow id as group id", -> + id = "1234-group-id" + process.env.CIRCLE_WORKFLOW_ID = id + expect(ciProvider.groupId()).to.equal(id) + + it "no group id without workflow id", -> + expect(ciProvider.groupId()).to.be.null + + it "returns 'unknown' when not found", -> process.env = {} diff --git a/packages/server/test/unit/modes/record_spec.coffee b/packages/server/test/unit/modes/record_spec.coffee index 71e235567d..cf373bfb54 100644 --- a/packages/server/test/unit/modes/record_spec.coffee +++ b/packages/server/test/unit/modes/record_spec.coffee @@ -11,6 +11,7 @@ record = require("#{root}../lib/modes/record") headless = require("#{root}../lib/modes/headless") git = require("#{root}../lib/util/git") ciProvider = require("#{root}../lib/util/ci_provider") +snapshot = require("snap-shot-it") describe "lib/modes/record", -> beforeEach -> @@ -70,19 +71,24 @@ describe "lib/modes/record", -> api.createRun.resolves() record.generateProjectBuildId("id-123", "/_test-output/path/to/project", "project", "key-123").then -> - expect(api.createRun).to.be.calledWith({ - projectId: "id-123" - recordKey: "key-123" - commitSha: "sha-123" - commitBranch: "master" - commitAuthorName: "brian" - commitAuthorEmail: "brian@cypress.io" - commitMessage: "such hax" - remoteOrigin: "https://github.com/foo/bar.git" - ciProvider: "circle" - ciBuildNumber: "build-123" - ciParams: {foo: "bar"} - }) + snapshot(api.createRun.firstCall.args) + + it "passes groupId", -> + api.createRun.resolves() + + group = true + groupId = "gr123" + record.generateProjectBuildId("id-123", "/_test-output/path/to/project", "project", "key-123", group, groupId).then -> + snapshot(api.createRun.firstCall.args) + + it "figures out groupId from CI environment variables", -> + @sandbox.stub(ciProvider, "groupId").returns("ci-group-123") + + api.createRun.resolves() + + group = true + record.generateProjectBuildId("id-123", "/_test-output/path/to/project", "project", "key-123", group).then -> + snapshot(api.createRun.firstCall.args) it "handles status code errors of 401", -> err = new Error