diff --git a/setup-env/README.md b/setup-env/README.md index 950a259..51b91b9 100644 --- a/setup-env/README.md +++ b/setup-env/README.md @@ -2,13 +2,13 @@ This action sets up the following environment variables in the runner environment. These environment variables shall be used in the tests for BrowserStack: -1. `BROWSERSTACK_BUILD_NAME`: This environment variable is set on the basis of the input to `build-name` field. By default, the value will be decided based on the event, i.e. push, pull_request etc for the workflow: +1. `BROWSERSTACK_BUILD_NAME`: This environment variable is set **only when you pass the `build-name` input**. If you do not pass it, the variable is left unset so that the build name configured in your own test setup (e.g. `browserstack.json` / `browserstack.yml`) is used. Pass the `BUILD_INFO` keyword to get a name generated from the event, i.e. push, pull_request etc for the workflow: 1. `push` event: `[] Commit : [Workflow: ]` 2. `pull_request` event: `[] PR : [Workflow: ]` 3. `release` event: `[] Release : [Workflow: ]` 4. Other events: ` [Workflow: ]` -2. `BROWSERSTACK_PROJECT_NAME`: This environment variable is set on the basis of the input to `project-name` field. By default, i.e. if any input is not provided, the value will be set as the Repository Name. +2. `BROWSERSTACK_PROJECT_NAME`: This environment variable is set **only when you pass the `project-name` input**. If you do not pass it, the variable is left unset so that the project name configured in your own test setup is used. Pass the `REPO_NAME` keyword to use the Repository Name. 3. `BROWSERSTACK_USERNAME`: This environment variable's value is taken from the input to `username` field. Ideal way would be to pass the GitHub Secret as the input, i.e. `username: ${{ secrets.BROWSERSTACK_USERNAME }}`. 4. `BROWSERSTACK_ACCESS_KEY`: This environment variable's value is taken from the input to `access-key` field. Ideal way would be to pass the GitHub Secret as the input, i.e. `access-key: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}`. @@ -46,10 +46,11 @@ or * `build-name: BUILD_INFO - My String at the end` * `build-name: String at the Beginning - BUILD_INFO - String at the end` * The keyword `BUILD_INFO` will be replaced by the information based on the event of the workflow as described above for `BROWSERSTACK_BUILD_NAME` environment variable. + * If you omit this input entirely, `BROWSERSTACK_BUILD_NAME` is **not** exported and your own configured build name is left untouched. * `project-name`: (**Optional**) * You can pass any string that you want to set as the `BROWSERSTACK_PROJECT_NAME`. E.g. `project-name: My Project Name Goes Here`. * You can also pass the keyword `REPO_NAME` as the input. This will set the Repository Name for the `BROWSERSTACK_PROJECT_NAME` environment variable. - * If no input is provided, `REPO_NAME` will be considered as the default input. + * If you omit this input entirely, `BROWSERSTACK_PROJECT_NAME` is **not** exported and your own configured project name is left untouched. --- **NOTE** diff --git a/setup-env/dist/index.js b/setup-env/dist/index.js index 9da6a06..cdd56d3 100644 --- a/setup-env/dist/index.js +++ b/setup-env/dist/index.js @@ -34599,6 +34599,10 @@ class ActionInput { // non-compulsory fields this.buildName = core.getInput(INPUT.BUILD_NAME); this.projectName = core.getInput(INPUT.PROJECT_NAME); + + // Capture before _validateInput() replaces blanks with generated defaults. + this.buildNameProvided = Boolean(this.buildName && this.buildName.trim()); + this.projectNameProvided = Boolean(this.projectName && this.projectName.trim()); this.githubApp = core.getInput(INPUT.GITHUB_APP); this.githubToken = core.getInput(INPUT.GITHUB_TOKEN); this.rerunAttempt = process?.env?.GITHUB_RUN_ATTEMPT; @@ -34632,13 +34636,23 @@ class ActionInput { core.exportVariable(ENV_VARS.BROWSERSTACK_ACCESS_KEY, this.accessKey); core.info(`Use ${ENV_VARS.BROWSERSTACK_ACCESS_KEY} environment variable for your access key in your tests\n`); - core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName); - core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`); - core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`); + // Export only when supplied: an env var outranks the user's browserstack.json, + // so a generated default would silently replace it. BUILD_INFO / REPO_NAME opt in. + if (this.projectNameProvided) { + core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName); + core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`); + core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`); + } else { + core.info(`No project-name input given, so ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} was left unset and your own configuration will be used. Pass project-name (or the REPO_NAME token) to set it here.\n`); + } - core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName); - core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`); - core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`); + if (this.buildNameProvided) { + core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName); + core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`); + core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`); + } else { + core.info(`No build-name input given, so ${ENV_VARS.BROWSERSTACK_BUILD_NAME} was left unset and your own configuration will be used. Pass build-name (or the BUILD_INFO token) to set it here.\n`); + } if (await this.checkIfBStackReRun()) { await this.setBStackRerunEnvVars(); diff --git a/setup-env/src/actionInput/index.js b/setup-env/src/actionInput/index.js index 95597c5..11c8c0c 100644 --- a/setup-env/src/actionInput/index.js +++ b/setup-env/src/actionInput/index.js @@ -32,6 +32,10 @@ class ActionInput { // non-compulsory fields this.buildName = core.getInput(INPUT.BUILD_NAME); this.projectName = core.getInput(INPUT.PROJECT_NAME); + + // Capture before _validateInput() replaces blanks with generated defaults. + this.buildNameProvided = Boolean(this.buildName && this.buildName.trim()); + this.projectNameProvided = Boolean(this.projectName && this.projectName.trim()); this.githubApp = core.getInput(INPUT.GITHUB_APP); this.githubToken = core.getInput(INPUT.GITHUB_TOKEN); this.rerunAttempt = process?.env?.GITHUB_RUN_ATTEMPT; @@ -65,13 +69,23 @@ class ActionInput { core.exportVariable(ENV_VARS.BROWSERSTACK_ACCESS_KEY, this.accessKey); core.info(`Use ${ENV_VARS.BROWSERSTACK_ACCESS_KEY} environment variable for your access key in your tests\n`); - core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName); - core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`); - core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`); + // Export only when supplied: an env var outranks the user's browserstack.json, + // so a generated default would silently replace it. BUILD_INFO / REPO_NAME opt in. + if (this.projectNameProvided) { + core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName); + core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`); + core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`); + } else { + core.info(`No project-name input given, so ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} was left unset and your own configuration will be used. Pass project-name (or the REPO_NAME token) to set it here.\n`); + } - core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName); - core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`); - core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`); + if (this.buildNameProvided) { + core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName); + core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`); + core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`); + } else { + core.info(`No build-name input given, so ${ENV_VARS.BROWSERSTACK_BUILD_NAME} was left unset and your own configuration will be used. Pass build-name (or the BUILD_INFO token) to set it here.\n`); + } if (await this.checkIfBStackReRun()) { await this.setBStackRerunEnvVars(); diff --git a/setup-env/test/actionInput/index.test.js b/setup-env/test/actionInput/index.test.js index 34460b1..bfab23a 100644 --- a/setup-env/test/actionInput/index.test.js +++ b/setup-env/test/actionInput/index.test.js @@ -48,6 +48,36 @@ describe('Action Input operations for fetching all inputs, triggering validation expect(actionInput.projectName).to.eq('validatedProjectName'); }); + it('Records that build-name and project-name were supplied', () => { + stubbedInput.withArgs(INPUT.BUILD_NAME).returns('someBuildName'); + stubbedInput.withArgs(INPUT.PROJECT_NAME).returns('someProjectName'); + const actionInput = new ActionInput(); + // eslint-disable-next-line no-unused-expressions + expect(actionInput.buildNameProvided).to.be.true; + // eslint-disable-next-line no-unused-expressions + expect(actionInput.projectNameProvided).to.be.true; + }); + + it('Records that build-name and project-name were NOT supplied when absent', () => { + stubbedInput.withArgs(INPUT.BUILD_NAME).returns(''); + stubbedInput.withArgs(INPUT.PROJECT_NAME).returns(''); + const actionInput = new ActionInput(); + // eslint-disable-next-line no-unused-expressions + expect(actionInput.buildNameProvided).to.be.false; + // eslint-disable-next-line no-unused-expressions + expect(actionInput.projectNameProvided).to.be.false; + }); + + it('Treats a whitespace-only name input as not supplied', () => { + stubbedInput.withArgs(INPUT.BUILD_NAME).returns(' '); + stubbedInput.withArgs(INPUT.PROJECT_NAME).returns('\t '); + const actionInput = new ActionInput(); + // eslint-disable-next-line no-unused-expressions + expect(actionInput.buildNameProvided).to.be.false; + // eslint-disable-next-line no-unused-expressions + expect(actionInput.projectNameProvided).to.be.false; + }); + it('Takes input and throws error if username is not provided in input', () => { stubbedInput.withArgs(INPUT.USERNAME, { required: true }).throws(Error('Username Required')); try { @@ -94,6 +124,9 @@ describe('Action Input operations for fetching all inputs, triggering validation actionInput.accessKey = 'someAccessKey'; actionInput.buildName = 'someBuildName'; actionInput.projectName = 'someProjectName'; + // _fetchAllInput is stubbed out above, so these flags have to be set by hand. + actionInput.buildNameProvided = true; + actionInput.projectNameProvided = true; // Stub checkIfBStackReRun to return true sinon.stub(actionInput, 'checkIfBStackReRun').returns(Promise.resolve(true)); @@ -111,6 +144,39 @@ describe('Action Input operations for fetching all inputs, triggering validation sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, 'someBuildName'); }); + it('Does not export BROWSERSTACK_PROJECT_NAME when no project-name input was given', () => { + actionInput.projectNameProvided = false; + actionInput.setEnvVariables(); + sinon.assert.neverCalledWith( + core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, sinon.match.any, + ); + // the other variables are unaffected + sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, 'someBuildName'); + sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_USERNAME, 'someUsername'); + }); + + it('Does not export BROWSERSTACK_BUILD_NAME when no build-name input was given', () => { + actionInput.buildNameProvided = false; + actionInput.setEnvVariables(); + sinon.assert.neverCalledWith( + core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, sinon.match.any, + ); + sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, 'someProjectName'); + sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_ACCESS_KEY, 'someAccessKey'); + }); + + it('Exports neither name when neither input was given, leaving the user config to win', () => { + actionInput.buildNameProvided = false; + actionInput.projectNameProvided = false; + actionInput.setEnvVariables(); + sinon.assert.neverCalledWith( + core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, sinon.match.any, + ); + sinon.assert.neverCalledWith( + core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, sinon.match.any, + ); + }); + it('Calls setBStackRerunEnvVars when checkIfBStackReRun returns true', async () => { const setBStackRerunEnvVarsStub = sinon.stub(actionInput, 'setBStackRerunEnvVars').resolves(); await actionInput.setEnvVariables();