Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

workspace_status_command should accept program on the PATH #4802

Closed
alexeagle opened this issue Mar 8, 2018 · 20 comments
Closed

workspace_status_command should accept program on the PATH #4802

alexeagle opened this issue Mar 8, 2018 · 20 comments
Assignees
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) type: feature request under investigation

Comments

@alexeagle
Copy link
Contributor

Currently workspace_status_command requires a path to a script in the project.

--workspace_status_command=<path> default: ""
A command invoked at the beginning of the build to provide status information about the workspace in the form of key/value pairs. See the User's Manual for the full specification.

This is hard to make portable between platforms. Making this a shell script means Windows developers on the team can't stamp binaries.

There is some discussion about this:
https://stackoverflow.com/questions/48159516/default-platform-specific-bazel-flags-in-bazel-rc
GerritCodeReview/gerrit@7a8f40f

The current solutions are workarounds.

The most convenient way to solve this IMO is to put a platform-independent script in the PATH, just like git subcommands (e.g. git-bazel-stamp). Then Bazel can always use --workspace_status_command=git-bazel-stamp and it's up to developers to install this git subcommand before stamping releases.

Thanks to @gregmagolan for pointing this out and @laszlocsomor for discussion

@laszlocsomor
Copy link
Contributor

I think this is a reasonable request and I can't think of a good workaround.
Implementation shouldn't be too hard: the Bazel client should look up the --wsc's argument from the PATH.

@lfpino : can the bazel client do this -- what I just wrote in the prev. sentence -- especially considering bazelrc files?

@lfpino
Copy link
Contributor

lfpino commented Mar 9, 2018

This issue reminds me of #964.

About your idea Laszlo, --workspace_status_command is parsed in the server so I don't see how the client can inspect the argument.

Maybe the solution is to bundle a platform-independent workspace_status_command in Bazel as suggested in #964 and make it the default value of the flag.

@laszlocsomor
Copy link
Contributor

@lfpino :

About your idea Laszlo, --workspace_status_command is parsed in the server so I don't see how the client can inspect the argument.

Can we change that? I mean can we parse the args in the client and if the argument starts with --workspace_status_command= or it's equal to --workspace_status_command then parse the path from it / from the following arg?

Alternatively, the server needs to know clientEnv["PATH"] to look up the path. I don't know if the server's options parser has access to the clientEnv. @lfpino , do you know?

@laszlocsomor
Copy link
Contributor

Luckily, all the machinery is in place:

this.getWorkspaceStatusCommand =
options.workspaceStatusCommand.equals(PathFragment.EMPTY_FRAGMENT)
? null
: new CommandBuilder()
.addArgs(options.workspaceStatusCommand.toString())
// Pass client env, because certain SCM client(like
// perforce, git) relies on environment variables to work
// correctly.
.setEnv(clientEnv)
.setWorkingDir(workspace)
.useShell(true)
.build();

This is where Bazel creates the Command to run the WSC. The clientEnv is already there, so Bazel could just look up the binary from clientEnv[PATH].

@laszlocsomor
Copy link
Contributor

FYI, I don't have the capacity to work on this.

@laszlocsomor laszlocsomor added the P3 We're not considering working on this, but happy to review a PR. (No assignee) label Mar 28, 2018
@laszlocsomor
Copy link
Contributor

laszlocsomor commented Apr 17, 2018

@alexeagle , I thought more about this problem, and it's transitively closely related to #5034 which is blocking #2190 which I ultimately care about.

I think --workspace_status_command should support absolute paths and workspace-root-relative paths. This way you could check in tools/bazelrc files to the depot with --workspace_status_command flags in them, and not rely on people having the referred script on their PATH but simply check it into the SCM. The path would have to be workspace-relative rather than PWD-relative, so you can still "bazel build" from any directory under the workspace.

@alexeagle , @lberki : WDYT?

@laszlocsomor
Copy link
Contributor

Bumping priority.

@laszlocsomor laszlocsomor added P1 I'll work on this now. (Assignee required) and removed P3 We're not considering working on this, but happy to review a PR. (No assignee) labels Apr 17, 2018
@lberki
Copy link
Contributor

lberki commented Apr 26, 2018

Yep, allowing --workspace_status_command to take either an absolute path or a workspace-relative one sounds reasonable.

In fact, it _almost works today, since one could say --workspace_status_command=./wsc.sh, except that PathFragmentConverter probably normalizes ./wsc.sh into wsc.sh which the shell doesn't find because the cwd is usually not on PATH

@lberki
Copy link
Contributor

lberki commented Apr 26, 2018

/proc/self/cwd/wsc.sh does work, though -- not a great workaround, but is a workaround. The cwd is guaranteed to be the workspace root when executing the workspace status command.

@alexeagle
Copy link
Contributor Author

That workaround doesn't help much given that the OP was for a setting that would work on Windows too.

@laszlocsomor
Copy link
Contributor

Sorry I dropped the ball on this bug for so long.

@alexeagle :

This is hard to make portable between platforms. Making this a shell script means Windows developers on the team can't stamp binaries.

Could you explain why they couldn't stamp binaries?

The most convenient way to solve this IMO is to put a platform-independent script in the PATH, just like git subcommands (e.g. git-bazel-stamp). Then Bazel can always use --workspace_status_command=git-bazel-stamp and it's up to developers to install this git subcommand before stamping releases.

What language would that script be written in?

Currently Bazel runs the --workspace_status_command through Bash on Unixes and through cmd.exe on Windows, which is why --workspace_status_command="echo FOO=bar" works on all platforms.

@alexeagle
Copy link
Contributor Author

If it's a shell script I can't run it on Windows, right?
How do the git subcommands work? In our case we would probably write the workspace status command in JavaScript and run it with nodejs.
Maybe the workspace status command would just be node path/to/script.js and this would work cross-platform?

@laszlocsomor
Copy link
Contributor

If it's a shell script I can't run it on Windows, right?

Right.

How do the git subcommands work?

Unfortunately I don't know. I reckon the git binary implements some of the commands, and looks up $0-${commandname} for the others.

In our case we would probably write the workspace status command in JavaScript and run it with nodejs.
Maybe the workspace status command would just be node path/to/script.js and this would work cross-platform?

Maybe it already does! Could you give it a try and comment here?

@enriched
Copy link

I was able to use node to output stamp vars with bazel v0.16.1 on windows and mac using:

.bazelrc

build --workspace_status_command "node ./build/bazel_stamp_vars.js"

./build/bazel_stamp_vars.js

#!/usr/bin/env node

const childProcess = require('child_process');
const execFile = childProcess.execFile;

function execStampVar(varName, executableFile, args) {
  return new Promise((resolve, reject) => {
    try {
      execFile(executableFile, args, (error, stdout, stderr) => {
        if (error) {
          reject(stderr);
        }
        resolve(`${varName} ${stdout}`);
      });
    } catch (e) {
      reject(e);
    }
  });
}

(async function writeStampVars() {
  const stampVarPromises = [
    execStampVar('GIT_COMMIT', 'git', ['rev-parse', 'HEAD']),
  ];

  const stampVars = await Promise.all(stampVarPromises);
  stampVars.forEach(sv => console.log(sv));
})()
  .then(() => process.exit(0))
  .catch(e => {
    console.error(`Writing stamp variables failed: ${e.message}`);
    process.exit(1);
  });

@alexeagle
Copy link
Contributor Author

@enriched thanks for demonstrating that! @laszlocsomor I think we could lower the priority.

My only remaining issue is that it requires that node be on your path already. In theory we'll have some full-stack developers who only install Bazel and expect the toolchain to be fetched and put in the external directory. Something like --workspace_status_command "$location(nodejs/node) ./build/bazel_stamp_vars.js" could work (if it understood standard execroot location expansion).

@laszlocsomor
Copy link
Contributor

Thanks @alexeagle and @enriched , I'll lower the priority.

@ulfjack
Copy link
Contributor

ulfjack commented Jan 22, 2019

We do pass PATH from the client environment through to the workspace action. It seems like it should look up the path on the PATH, doesn't it?

@laszlocsomor
Copy link
Contributor

How do you know that the string contains the path of an executable vs. a Bash command?

@ulfjack
Copy link
Contributor

ulfjack commented Feb 12, 2019

Remove support for bash commands?

@laszlocsomor
Copy link
Contributor

I doubt we can just remove support for Bash commands, as there are users relying on this feature who would likely miss it.

See: #5002 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) type: feature request under investigation
Projects
None yet
Development

No branches or pull requests

6 participants