Skip to content

Commit e6365c7

Browse files
shivamku-BSclaude
authored andcommitted
fix(setup-env): do not override a build/project name the workflow never set
setEnvVariables() exported BROWSERSTACK_BUILD_NAME and BROWSERSTACK_PROJECT_NAME unconditionally. When the workflow supplied neither input, _validateInput() had already replaced them with generated defaults -- the repo name, and "<event> [Workflow: <n>]" -- so the action exported values the user never asked for. Every BrowserStack SDK resolves names as CLI args > env vars > config file. An exported default therefore does not fill a gap, it OUTRANKS whatever the user configured and silently replaces it. A customer following our own documented setup for re-run delivery saw their browserstack.json project_name/build_name of "E2E_Automation" replaced by "core-automation-framework" and "workflow_dispatch [Workflow: 7]". Export each variable only when its input was actually supplied. The generated values remain available through the BUILD_INFO and REPO_NAME tokens that InputValidator already understands -- which is what those tokens were for. When an input is omitted the action now logs that it left the variable unset, so the behaviour is visible in the workflow log. Ref: SDK-7461 (follow-on to SDK-7124) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 1ab56d9 commit e6365c7

4 files changed

Lines changed: 126 additions & 15 deletions

File tree

‎setup-env/README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
This action sets up the following environment variables in the runner environment. These environment variables shall be used in the tests for BrowserStack:
44

5-
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:
5+
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:
66
1. `push` event: `[<Branch-Name>] Commit <commit-sha>: <commit-message> [Workflow: <Workflow-number>]`
77
2. `pull_request` event: `[<Branch-Name>] PR <PR-number>: <PR-title> [Workflow: <Workflow-number>]`
88
3. `release` event: `[<Branch-Name>] Release <Release-tag>: <Release-name> [Workflow: <Workflow-number>]`
99
4. Other events: `<Event-Name> [Workflow: <Workflow-number>]`
1010

11-
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.
11+
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.
1212
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 }}`.
1313
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 }}`.
1414

@@ -46,10 +46,11 @@ or
4646
* `build-name: BUILD_INFO - My String at the end`
4747
* `build-name: String at the Beginning - BUILD_INFO - String at the end`
4848
* 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.
49+
* If you omit this input entirely, `BROWSERSTACK_BUILD_NAME` is **not** exported and your own configured build name is left untouched.
4950
* `project-name`: (**Optional**)
5051
* You can pass any string that you want to set as the `BROWSERSTACK_PROJECT_NAME`. E.g. `project-name: My Project Name Goes Here`.
5152
* You can also pass the keyword `REPO_NAME` as the input. This will set the Repository Name for the `BROWSERSTACK_PROJECT_NAME` environment variable.
52-
* If no input is provided, `REPO_NAME` will be considered as the default input.
53+
* If you omit this input entirely, `BROWSERSTACK_PROJECT_NAME` is **not** exported and your own configured project name is left untouched.
5354

5455
---
5556
**NOTE**

‎setup-env/dist/index.js‎

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34599,6 +34599,12 @@ class ActionInput {
3459934599
// non-compulsory fields
3460034600
this.buildName = core.getInput(INPUT.BUILD_NAME);
3460134601
this.projectName = core.getInput(INPUT.PROJECT_NAME);
34602+
34603+
// Whether the workflow actually asked us for a name. _validateInput() replaces
34604+
// both fields with generated defaults when they are blank, so the only place
34605+
// this can be observed is here, before validation runs.
34606+
this.buildNameProvided = Boolean(this.buildName && this.buildName.trim());
34607+
this.projectNameProvided = Boolean(this.projectName && this.projectName.trim());
3460234608
this.githubApp = core.getInput(INPUT.GITHUB_APP);
3460334609
this.githubToken = core.getInput(INPUT.GITHUB_TOKEN);
3460434610
this.rerunAttempt = process?.env?.GITHUB_RUN_ATTEMPT;
@@ -34632,13 +34638,29 @@ class ActionInput {
3463234638
core.exportVariable(ENV_VARS.BROWSERSTACK_ACCESS_KEY, this.accessKey);
3463334639
core.info(`Use ${ENV_VARS.BROWSERSTACK_ACCESS_KEY} environment variable for your access key in your tests\n`);
3463434640

34635-
core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName);
34636-
core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`);
34637-
core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`);
34641+
// Only export the name variables when the workflow actually supplied them.
34642+
//
34643+
// Every BrowserStack SDK resolves names as: CLI args > env vars > config file.
34644+
// Exporting a generated default here therefore does not "fill a gap" -- it
34645+
// OUTRANKS whatever the user configured in browserstack.json / browserstack.yml
34646+
// and silently replaces it. Users who want the generated values still get them
34647+
// by opting in with the `BUILD_INFO` and `REPO_NAME` tokens, which
34648+
// InputValidator already understands.
34649+
if (this.projectNameProvided) {
34650+
core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName);
34651+
core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`);
34652+
core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`);
34653+
} else {
34654+
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`);
34655+
}
3463834656

34639-
core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName);
34640-
core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`);
34641-
core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`);
34657+
if (this.buildNameProvided) {
34658+
core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName);
34659+
core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`);
34660+
core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`);
34661+
} else {
34662+
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`);
34663+
}
3464234664

3464334665
if (await this.checkIfBStackReRun()) {
3464434666
await this.setBStackRerunEnvVars();

‎setup-env/src/actionInput/index.js‎

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class ActionInput {
3232
// non-compulsory fields
3333
this.buildName = core.getInput(INPUT.BUILD_NAME);
3434
this.projectName = core.getInput(INPUT.PROJECT_NAME);
35+
36+
// Whether the workflow actually asked us for a name. _validateInput() replaces
37+
// both fields with generated defaults when they are blank, so the only place
38+
// this can be observed is here, before validation runs.
39+
this.buildNameProvided = Boolean(this.buildName && this.buildName.trim());
40+
this.projectNameProvided = Boolean(this.projectName && this.projectName.trim());
3541
this.githubApp = core.getInput(INPUT.GITHUB_APP);
3642
this.githubToken = core.getInput(INPUT.GITHUB_TOKEN);
3743
this.rerunAttempt = process?.env?.GITHUB_RUN_ATTEMPT;
@@ -65,13 +71,29 @@ class ActionInput {
6571
core.exportVariable(ENV_VARS.BROWSERSTACK_ACCESS_KEY, this.accessKey);
6672
core.info(`Use ${ENV_VARS.BROWSERSTACK_ACCESS_KEY} environment variable for your access key in your tests\n`);
6773

68-
core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName);
69-
core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`);
70-
core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`);
74+
// Only export the name variables when the workflow actually supplied them.
75+
//
76+
// Every BrowserStack SDK resolves names as: CLI args > env vars > config file.
77+
// Exporting a generated default here therefore does not "fill a gap" -- it
78+
// OUTRANKS whatever the user configured in browserstack.json / browserstack.yml
79+
// and silently replaces it. Users who want the generated values still get them
80+
// by opting in with the `BUILD_INFO` and `REPO_NAME` tokens, which
81+
// InputValidator already understands.
82+
if (this.projectNameProvided) {
83+
core.exportVariable(ENV_VARS.BROWSERSTACK_PROJECT_NAME, this.projectName);
84+
core.info(`${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable set as: ${this.projectName}`);
85+
core.info(`Use ${ENV_VARS.BROWSERSTACK_PROJECT_NAME} environment variable for your project name capability in your tests\n`);
86+
} else {
87+
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`);
88+
}
7189

72-
core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName);
73-
core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`);
74-
core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`);
90+
if (this.buildNameProvided) {
91+
core.exportVariable(ENV_VARS.BROWSERSTACK_BUILD_NAME, this.buildName);
92+
core.info(`${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable set as: ${this.buildName}`);
93+
core.info(`Use ${ENV_VARS.BROWSERSTACK_BUILD_NAME} environment variable for your build name capability in your tests\n`);
94+
} else {
95+
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`);
96+
}
7597

7698
if (await this.checkIfBStackReRun()) {
7799
await this.setBStackRerunEnvVars();

‎setup-env/test/actionInput/index.test.js‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,36 @@ describe('Action Input operations for fetching all inputs, triggering validation
4848
expect(actionInput.projectName).to.eq('validatedProjectName');
4949
});
5050

51+
it('Records that build-name and project-name were supplied', () => {
52+
stubbedInput.withArgs(INPUT.BUILD_NAME).returns('someBuildName');
53+
stubbedInput.withArgs(INPUT.PROJECT_NAME).returns('someProjectName');
54+
const actionInput = new ActionInput();
55+
// eslint-disable-next-line no-unused-expressions
56+
expect(actionInput.buildNameProvided).to.be.true;
57+
// eslint-disable-next-line no-unused-expressions
58+
expect(actionInput.projectNameProvided).to.be.true;
59+
});
60+
61+
it('Records that build-name and project-name were NOT supplied when absent', () => {
62+
stubbedInput.withArgs(INPUT.BUILD_NAME).returns('');
63+
stubbedInput.withArgs(INPUT.PROJECT_NAME).returns('');
64+
const actionInput = new ActionInput();
65+
// eslint-disable-next-line no-unused-expressions
66+
expect(actionInput.buildNameProvided).to.be.false;
67+
// eslint-disable-next-line no-unused-expressions
68+
expect(actionInput.projectNameProvided).to.be.false;
69+
});
70+
71+
it('Treats a whitespace-only name input as not supplied', () => {
72+
stubbedInput.withArgs(INPUT.BUILD_NAME).returns(' ');
73+
stubbedInput.withArgs(INPUT.PROJECT_NAME).returns('\t ');
74+
const actionInput = new ActionInput();
75+
// eslint-disable-next-line no-unused-expressions
76+
expect(actionInput.buildNameProvided).to.be.false;
77+
// eslint-disable-next-line no-unused-expressions
78+
expect(actionInput.projectNameProvided).to.be.false;
79+
});
80+
5181
it('Takes input and throws error if username is not provided in input', () => {
5282
stubbedInput.withArgs(INPUT.USERNAME, { required: true }).throws(Error('Username Required'));
5383
try {
@@ -94,6 +124,9 @@ describe('Action Input operations for fetching all inputs, triggering validation
94124
actionInput.accessKey = 'someAccessKey';
95125
actionInput.buildName = 'someBuildName';
96126
actionInput.projectName = 'someProjectName';
127+
// _fetchAllInput is stubbed out above, so these flags have to be set by hand.
128+
actionInput.buildNameProvided = true;
129+
actionInput.projectNameProvided = true;
97130

98131
// Stub checkIfBStackReRun to return true
99132
sinon.stub(actionInput, 'checkIfBStackReRun').returns(Promise.resolve(true));
@@ -111,6 +144,39 @@ describe('Action Input operations for fetching all inputs, triggering validation
111144
sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, 'someBuildName');
112145
});
113146

147+
it('Does not export BROWSERSTACK_PROJECT_NAME when no project-name input was given', () => {
148+
actionInput.projectNameProvided = false;
149+
actionInput.setEnvVariables();
150+
sinon.assert.neverCalledWith(
151+
core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, sinon.match.any,
152+
);
153+
// the other variables are unaffected
154+
sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, 'someBuildName');
155+
sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_USERNAME, 'someUsername');
156+
});
157+
158+
it('Does not export BROWSERSTACK_BUILD_NAME when no build-name input was given', () => {
159+
actionInput.buildNameProvided = false;
160+
actionInput.setEnvVariables();
161+
sinon.assert.neverCalledWith(
162+
core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, sinon.match.any,
163+
);
164+
sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, 'someProjectName');
165+
sinon.assert.calledWith(core.exportVariable, ENV_VARS.BROWSERSTACK_ACCESS_KEY, 'someAccessKey');
166+
});
167+
168+
it('Exports neither name when neither input was given, leaving the user config to win', () => {
169+
actionInput.buildNameProvided = false;
170+
actionInput.projectNameProvided = false;
171+
actionInput.setEnvVariables();
172+
sinon.assert.neverCalledWith(
173+
core.exportVariable, ENV_VARS.BROWSERSTACK_BUILD_NAME, sinon.match.any,
174+
);
175+
sinon.assert.neverCalledWith(
176+
core.exportVariable, ENV_VARS.BROWSERSTACK_PROJECT_NAME, sinon.match.any,
177+
);
178+
});
179+
114180
it('Calls setBStackRerunEnvVars when checkIfBStackReRun returns true', async () => {
115181
const setBStackRerunEnvVarsStub = sinon.stub(actionInput, 'setBStackRerunEnvVars').resolves();
116182
await actionInput.setEnvVariables();

0 commit comments

Comments
 (0)