Skip to content

Commit

Permalink
Make tsconfig default to label //:tsconfig.json
Browse files Browse the repository at this point in the history
This avoids the need for users to create their own ts_library macro to follow the best-practice of having the same tsconfig.json for all libraries, and fixes the issue that it's easy to have no tsconfig applied to a ts_library if the attribute is omitted

BREAKING CHANGE:
ts_library targets with no tsconfig attribute will now
default to //:tsconfig.json.

If this breaks you, do one of these:
1) create a file at that location (in the WORKSPACE root)
2) create an alias rule in the root BUILD.bazel file like
     alias(name="tsconfig.json", actual="//path/to:tsconfig-something.json")
3) give an explicit tsconfig attribute to your ts_library rules

Closes bazel-contrib#232

PiperOrigin-RevId: 205759471
  • Loading branch information
alexeagle committed Jul 24, 2018
1 parent 6fbede9 commit 1c40aeb
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
load("@io_bazel_rules_go//go:def.bzl", "gazelle")
load("@build_bazel_rules_nodejs//internal/js_library:js_library.bzl", "js_library")

# ts_library defaults to this label in the top-level package.
# Point to where the file actually lives.
alias(
name = "tsconfig.json",
actual = "//examples:tsconfig.json",
visibility = ["//visibility:public"],
)

gazelle(
name = "gazelle",
prefix = "github.com/bazelbuild/rules_typescript",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
Users should not load files under "/internal"
"""
load("//internal:ts_repositories.bzl", _ts_setup_workspace = "ts_setup_workspace")
load("//internal:build_defs.bzl", _ts_library = "ts_library")
load("//internal:build_defs.bzl", _ts_library = "ts_library_macro")
load("//internal:ts_config.bzl", _ts_config = "ts_config")
load("//internal/devserver:ts_devserver.bzl", _ts_devserver = "ts_devserver_macro")
load("//internal/karma:ts_web_test.bzl",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
package(default_visibility = ["//visibility:public"])

exports_files([
"tsconfig.json",
# Exported to be consumed for generating skydoc.
"build_defs.bzl",
"ts_config.bzl",
"ts_repositories.bzl",
])

load("//internal:build_defs.bzl", "ts_library")
load("//:defs.bzl", "ts_library")
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary", "jasmine_node_test")

# Vanilla typescript compiler: run the tsc.js binary distributed by TypeScript
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def _ts_library_impl(ctx):
)
return ts_providers_dict_to_struct(ts_providers)

ts_library = rule(
_ts_library = rule(
_ts_library_impl,
attrs = dict(COMMON_ATTRIBUTES, **{
"srcs": attr.label_list(
Expand Down Expand Up @@ -217,3 +217,9 @@ ts_library = rule(
It produces declarations files (`.d.ts`) which are used for compiling downstream
TypeScript targets and JavaScript for the browser and Closure compiler.
"""

def ts_library_macro(tsconfig = None, **kwargs):
if not tsconfig:
tsconfig = "//:tsconfig.json"

_ts_library(tsconfig = tsconfig, **kwargs)
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/**
* @fileoverview
* This tests interactions between multiple Bazel workspaces.
*
* We have learned from experience in the rules_nodejs repo that it's not
* practical to simply check in the nested WORKSPACE files and try to build
* them, because
* - it's hard to exclude them from the parent WORKSPACE - each nested workspace
* must be registered there with a matching name
* - testing a child workspace requires `cd` into the directory, which doesn't
* fit the CI model of `bazel test ...`
*
* The test is written in JavaScript simply to make it more portable, so we can
* run it on Windows for example. We don't use TypeScript here since we are
* running outside the build system.
*/

const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const os = require('os');

const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'wksp'));
const WORKSPACE_BOILERPLATE = `
http_archive(
name = "build_bazel_rules_nodejs",
urls = ["https://github.com/bazelbuild/rules_nodejs/archive/0.10.0.zip"],
strip_prefix = "rules_nodejs-0.10.0",
)
http_archive(
name = "io_bazel_rules_webtesting",
urls = ["https://github.com/bazelbuild/rules_webtesting/archive/v0.2.0.zip"],
strip_prefix = "rules_webtesting-0.2.0",
)
http_archive(
name = "io_bazel_rules_go",
urls = [
"http://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/0.10.3/rules_go-0.10.3.tar.gz",
"https://github.com/bazelbuild/rules_go/releases/download/0.10.3/rules_go-0.10.3.tar.gz"
],
)
local_repository(
name = "build_bazel_rules_typescript",
path = "${process.cwd()}",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(package_json=[])
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
ts_setup_workspace()
`;

/**
* Create a file at path filename, creating parent directories as needed, under
* this test's temp directory. Write the content into that file.
*/
function write(filename, content) {
var parents = path.dirname(path.join(tmpdir, filename));
while (path.dirname(parents) !== parents) {
if (!fs.existsSync(path.join(parents))) {
fs.mkdirSync(path.join(parents));
}
parents = path.dirname(parents);
}
fs.writeFileSync(path.join(tmpdir, filename), content);
}

function bazel(workspace, args) {
const result = child_process.spawnSync('bazel', args, {
cwd: path.join(tmpdir, workspace),
stdio: 'inherit',
});
expect(result.status).toBe(0, 'bazel exited with non-zero exit code');
}

describe('default tsconfig', () => {
it(`uses the tsconfig in the workspace defining the rule,
not the workspace where the rule is defined (rules_typescript), nor
the workspace where the build is occurring`,
() => {
// Workspace 'a' can't compile with --noImplicitAny.
// When workspace 'b' has a dep here, we make sure not to use the
// tsconfig from workspace 'b'
write('a/WORKSPACE', `
workspace(name = "a")
${WORKSPACE_BOILERPLATE}`);
write('a/BUILD', `
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
ts_library(
name = "a_lib",
srcs=["has_implicit_any.ts"],
node_modules = "@build_bazel_rules_typescript_tsc_wrapped_deps//:node_modules",
visibility = ["//visibility:public"],
)
`);
write('a/tsconfig.json', `{}`);
write('a/has_implicit_any.ts', `function f(a) {
console.error(a);
}`);

// Workspace 'b' has a default tsconfig that sets --noImplicitAny.
write('b/WORKSPACE', `
workspace(name="b")
local_repository(name="a", path="../a")
${WORKSPACE_BOILERPLATE}`);
write('b/BUILD', `
load("@build_bazel_rules_typescript//:defs.bzl", "ts_library")
exports_files(["tsconfig.json"])
ts_library(
name = "b_lib",
srcs = ["file.ts"],
deps = ["@a//:a_lib"],
node_modules = "@build_bazel_rules_typescript_tsc_wrapped_deps//:node_modules",
)
`);
write('b/file.ts', `
f('thing');
`);
write('b/tsconfig.json', `{
"compilerOptions": {
"noImplicitAny": true
}
}`);

// Now build from workspace 'b' and verify that the dep in workspace 'a'
// was able to compile.
bazel('b', ['build', ':all']);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ts_library(
srcs = glob(["*.ts"]),
module_name = "karma-concat-js",
node_modules = "@build_bazel_rules_typescript_tsc_wrapped_deps//:node_modules",
tsconfig = "//internal:tsconfig.json",
)

load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
},
"scripts": {
"pree2e": "webdriver-manager update $CHROMEDRIVER_VERSION_ARG && bazel build examples/app:e2e && bazel build examples/protocol_buffers:e2e",
"e2e": "yarn e2e-examples-app-devserver && yarn e2e-examples-app-prodserver && yarn e2e-examples-protobuf-devserver && yarn e2e-examples-protobuf-prodserver",
"e2e": "yarn e2e-bazel-external && yarn e2e-examples-app-devserver && yarn e2e-examples-app-prodserver && yarn e2e-examples-protobuf-devserver && yarn e2e-examples-protobuf-prodserver",
"e2e-bazel-external": "jasmine internal/e2e/default_tsconfig_test.js",
"e2e-examples-app-devserver": "concurrently \"bazel run examples/app:devserver\" \"while ! nc -z 127.0.0.1 8080; do sleep 1; done && protractor --suite app\" --kill-others --success first",
"e2e-examples-app-prodserver": "concurrently \"bazel run examples/app:prodserver\" \"while ! nc -z 127.0.0.1 8080; do sleep 1; done && protractor --suite app\" --kill-others --success first",
"e2e-examples-protobuf-devserver": "concurrently \"bazel run examples/protocol_buffers:devserver\" \"while ! nc -z 127.0.0.1 8080; do sleep 1; done && protractor --suite protocol_buffers\" --kill-others --success first",
Expand Down

0 comments on commit 1c40aeb

Please sign in to comment.