Skip to content

Commit 4e7dd1b

Browse files
authored
feat: add check_for_update (#439)
* feat: add check_for_update * Update WORKSPACE * chore: code review comments * Update npm_repositories.bzl More code review comment * chore: count unversioned uses too
1 parent b191078 commit 4e7dd1b

File tree

4 files changed

+92
-6
lines changed

4 files changed

+92
-6
lines changed

docs/repositories.md

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ts/extensions.bzl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ def _extension_impl(module_ctx):
1111
ts_version = attr.ts_version
1212
if not ts_version and not attr.ts_version_from:
1313
ts_version = LATEST_TYPESCRIPT_VERSION
14-
npm_dependencies(ts_version = ts_version, ts_version_from = attr.ts_version_from, ts_integrity = attr.ts_integrity)
14+
npm_dependencies(
15+
ts_version = ts_version,
16+
ts_version_from = attr.ts_version_from,
17+
ts_integrity = attr.ts_integrity,
18+
check_for_updates = attr.check_for_updates,
19+
bzlmod = True,
20+
)
1521

1622
ext = module_extension(
1723
implementation = _extension_impl,
@@ -20,6 +26,7 @@ ext = module_extension(
2026
"ts_version": attr.string(),
2127
"ts_version_from": attr.label(),
2228
"ts_integrity": attr.string(),
29+
"check_for_updates": attr.bool(default = True),
2330
}),
2431
},
2532
)

ts/private/npm_repositories.bzl

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Runtime dependencies fetched from npm"""
22

33
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
4-
load("//ts/private:versions.bzl", "TOOL_VERSIONS")
4+
load("//ts/private:versions.bzl", "RULES_TS_VERSION", "TOOL_VERSIONS")
55

66
worker_versions = struct(
77
bazel_worker_version = "5.4.2",
@@ -10,6 +10,17 @@ worker_versions = struct(
1010
google_protobuf_integrity = "sha512-XMf1+O32FjYIV3CYu6Tuh5PNbfNEU5Xu22X+Xkdb/DUexFlCzhvv7d5Iirm4AOwn8lv4al1YvIhzGrg2j9Zfzw==",
1111
)
1212

13+
# Keep this list in sync with user documentation.
14+
# We must inform users what we gather from their builds.
15+
_TELEMETRY_VARS = [
16+
"BUILDKITE_BUILD_NUMBER",
17+
"BUILDKITE_ORGANIZATION_SLUG",
18+
"CIRCLE_BUILD_NUM",
19+
"CIRCLE_PROJECT_USERNAME",
20+
"GITHUB_REPOSITORY_OWNER",
21+
"GITHUB_RUN_NUMBER",
22+
]
23+
1324
def _http_archive_version_impl(rctx):
1425
integrity = None
1526
if rctx.attr.version:
@@ -63,10 +74,54 @@ def _http_archive_version_impl(rctx):
6374
executable = False,
6475
)
6576

77+
if rctx.attr.check_for_updates:
78+
_check_for_updates(rctx)
79+
80+
def _check_for_updates(rctx):
81+
version = RULES_TS_VERSION
82+
83+
# If the placeholder string wasn't replaced, that means we aren't running from a release artifact.
84+
# It might be a SHA from GitHub, or a fork of the repo, etc.
85+
# We won't be able to say if an update is available, but we count these uses.
86+
if version.startswith("$Format"):
87+
version = "v0.0.0"
88+
89+
vars = ["{}={}".format(v, rctx.os.environ[v]) for v in _TELEMETRY_VARS if v in rctx.os.environ]
90+
if rctx.attr.bzlmod:
91+
vars.append("bzlmod=true")
92+
url = "https://update.aspect.build/aspect_rules_ts/{}?{}".format(
93+
version,
94+
"&".join(vars),
95+
)
96+
output_path = str(rctx.path(".output/update_check_result"))
97+
command = ["curl", url, "--write-out", "%{http_code}", "--output", output_path]
98+
99+
# Avoid stalling the users Bazel session
100+
command.extend(["--connect-timeout", "1", "--max-time", "1"])
101+
result = rctx.execute(command)
102+
if result.return_code != 0:
103+
# Ignore failures when trying to check for new version
104+
return
105+
status_code = int(result.stdout.strip())
106+
107+
# 302 Found redirect status response code indicates that the resource requested has been temporarily moved to the URL given by the Location header.
108+
# Don't bother the user with any other status code
109+
if status_code != 302:
110+
return
111+
112+
# buildifier: disable=print
113+
# TODO: print content of output_path which now has the link to the newer version
114+
print("""\
115+
NOTICE: a newer version of rules_ts is available.
116+
See https://github.com/aspect-build/rules_ts/releases
117+
""")
118+
66119
http_archive_version = repository_rule(
67120
doc = "Re-implementation of http_archive that can read the version from package.json",
68121
implementation = _http_archive_version_impl,
69122
attrs = {
123+
"bzlmod": attr.bool(doc = "Whether we were called from a bzlmod module extension"),
124+
"check_for_updates": attr.bool(doc = "Whether to check for a newer version of rules_ts"),
70125
"integrity": attr.string(doc = "Needed only if the ts version isn't mirrored in `versions.bzl`."),
71126
"version": attr.string(doc = "Explicit version for `urls` placeholder. If provided, the package.json is not read."),
72127
"urls": attr.string_list(doc = "URLs to fetch from. Each must have one `{}`-style placeholder."),
@@ -77,13 +132,15 @@ http_archive_version = repository_rule(
77132
)
78133

79134
# buildifier: disable=function-docstring
80-
def npm_dependencies(ts_version_from = None, ts_version = None, ts_integrity = None):
135+
def npm_dependencies(ts_version_from = None, ts_version = None, ts_integrity = None, bzlmod = False, check_for_updates = True):
81136
if (ts_version and ts_version_from) or (not ts_version_from and not ts_version):
82137
fail("""Exactly one of 'ts_version' or 'ts_version_from' must be set.""")
83138

84139
maybe(
85140
http_archive_version,
86141
name = "npm_typescript",
142+
bzlmod = bzlmod,
143+
check_for_updates = check_for_updates,
87144
version = ts_version,
88145
version_from = ts_version_from,
89146
integrity = ts_integrity,

ts/repositories.bzl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def rules_ts_bazel_dependencies():
4747
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.8.2/rules_nodejs-core-5.8.2.tar.gz"],
4848
)
4949

50-
def rules_ts_dependencies(ts_version_from = None, ts_version = None, ts_integrity = None):
50+
def rules_ts_dependencies(ts_version_from = None, ts_version = None, ts_integrity = None, check_for_updates = True):
5151
"""Dependencies needed by users of rules_ts.
5252
5353
To skip fetching the typescript package, call `rules_ts_bazel_dependencies` instead.
@@ -69,8 +69,29 @@ def rules_ts_dependencies(ts_version_from = None, ts_version = None, ts_integrit
6969
By default, uses values mirrored into rules_ts.
7070
For example, to get the integrity of version 4.6.3 you could run
7171
`curl --silent https://registry.npmjs.org/typescript/4.6.3 | jq -r '.dist.integrity'`
72+
check_for_updates: Whether to check for newer releases of rules_ts and notify the user with
73+
a log message when an update is available.
74+
75+
Note, to better understand our users, we also include basic information about the build
76+
in the request to the update server. This never includes confidential or
77+
personally-identifying information (PII). The values sent are:
78+
79+
- Currently used version. Helps us understand which older release(s) users are stuck on.
80+
- bzlmod (true/false). Helps us roll out this feature which is mandatory by Bazel 9.
81+
- Some CI-related environment variables to understand usage:
82+
- BUILDKITE_ORGANIZATION_SLUG
83+
- CIRCLE_PROJECT_USERNAME (this is *not* the username of the logged in user)
84+
- GITHUB_REPOSITORY_OWNER
85+
- BUILDKITE_BUILD_NUMBER
86+
- CIRCLE_BUILD_NUM
87+
- GITHUB_RUN_NUMBER
7288
"""
7389

7490
rules_ts_bazel_dependencies()
7591

76-
npm_dependencies(ts_version_from = ts_version_from, ts_version = ts_version, ts_integrity = ts_integrity)
92+
npm_dependencies(
93+
ts_version_from = ts_version_from,
94+
ts_version = ts_version,
95+
ts_integrity = ts_integrity,
96+
check_for_updates = check_for_updates,
97+
)

0 commit comments

Comments
 (0)