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

incompatible_use_remotejdk_as_host_javabase: use remote JDK for building Java #6656

Open
meisterT opened this Issue Nov 12, 2018 · 15 comments

Comments

Projects
None yet
7 participants
@meisterT
Copy link
Member

meisterT commented Nov 12, 2018

The option --incompatible_use_remotejdk_as_host_javabase allows us to remove the dependency from the host javabase on the embedded JDK.

More discussion in:
https://docs.google.com/document/d/11OGJ2QTjnZgxbkgVFrKa3eD2DQ68qnXws7UQ1czc-qQ/edit#heading=h.5dewu068k9gb

Migration notes

  • If you set the flag, Bazel will download the JDK from a remote repository (see https://github.com/bazelbuild/bazel/pull/6216/files#diff-b53d77ce419e665f48b6c7bca4965357).
  • That JDK will be used to run the Java compiler (cf --host_javabase)
  • This will only happen if you actually build Java or use $(JAVA) or $(JAVABASE) in your genrules. Non-java devs are not affected.
  • If you want to avoid downloading the JDK (e.g. in CI settings) for Java builds, you can explicitly set the --host_javabase, e.g., to @local_jdk//:jdk.
@meisterT

This comment has been minimized.

Copy link
Member

meisterT commented Nov 12, 2018

We plan to flip the flag (and remove the old code) in the 0.21 release.

@dslomov

This comment has been minimized.

Copy link
Contributor

dslomov commented Nov 12, 2018

Could you write a more concise explanation in the issue of

  • what the flag does
  • who is affected
  • how to fix
@dslomov

This comment has been minimized.

Copy link
Contributor

dslomov commented Nov 12, 2018

(once that is done, add 'migration-0.20' and 'breaking-change-0.21' labels back.

@meisterT

This comment has been minimized.

Copy link
Member

meisterT commented Nov 12, 2018

  • If you set the flag, Bazel will download the JDK from a remote repository (see https://github.com/bazelbuild/bazel/pull/6216/files#diff-b53d77ce419e665f48b6c7bca4965357).
  • This will only happen if you actually build Java or use $(JAVA) or $(JAVABASE) in your genrules. Non-java devs are not affected.
  • How to fix: the version of the embedded JDK and the new default JDK are identical. And I already pointed out how to do work around the additional download (if necessary) in the first comment.
@davido

This comment has been minimized.

Copy link
Contributor

davido commented Nov 12, 2018

If you want to avoid downloading the JDK (e.g. in CI settings) for Java builds, you can explicitly set the --host_javabase, e.g., to @local_jdk//:jdk.

Another approach is to include bazel build //... in CI docker image build step. Then the right JDK will be downloaded and cached in CI Docker image.

@dslomov dslomov changed the title --incompatible_use_remotejdk_as_host_javabase incompatible_use_remotejdk_as_host_javabase: use remote JDK for building Java Nov 13, 2018

bazel-io pushed a commit that referenced this issue Nov 30, 2018

Release 0.20.0 (2018-11-30)
Baseline: 7bf7f03

Cherry picks:

   + fd52341:
     update bazel-toolchains pin to latest release Part of changes to
     allow bazelci to use 0.19.0 configs. RBE toolchain configs at or
     before 0.17.0 are not compatible with bazel 0.19.0 or above.
   + 241f28d:
     Revert "Toggle --incompatible_disable_late_bound_option_defaults
     flag."
   + f7e5aef:
     Add cc_toolchain targets for the new entries in the default
     cc_toolchain_suite.
   + d2920e3:
     Revert "WindowsFileSystem: open files with delete-sharing"

[Breaking changes in 0.20](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Abreaking-change-0.20)

  - [--incompatible_remove_native_http_archive](#6570).
  - [--incompatible_remove_native_git_repository](#6569).
  - [--incompatible_disable_cc_toolchain_label_from_crosstool_proto](#6434).
  - [--incompatible_disable_depset_in_cc_user_flags](#6384).
  - [--incompatible_disable_cc_configuration_make_variables](#6381).
  - [--incompatible_disallow_conflicting_providers](#5902).
  - [--incompatible_range_type](#5264).

[0.20 is a migration window for the following changes](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Amigration-0.20)

  - [--incompatible_use_jdk10_as_host_javabase](#6661)
  - [--incompatible_use_remotejdk_as_host_javabase](#6656)
  - [--incompatible_disable_sysroot_from_configuration](#6565)
  - [--incompatible_provide_cc_toolchain_info_from_cc_toolchain_suite](#6537)
  - [--incompatible_disable_depset_in_cc_user_flags](#6383)
  - [--incompatible_package_name_is_a_function](#5827)

[Breaking changes in the next release (0.21)](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Abreaking-change-0.21)

  - [--incompatible_use_jdk10_as_host_javabase](#6661)
  - [--incompatible_use_remotejdk_as_host_javabase](#6656)
  - [--incompatible_disable_sysroot_from_configuration](#6565)
  - [--incompatible_provide_cc_toolchain_info_from_cc_toolchain_suite](#6537)
  - [--incompatible_disable_depset_in_cc_user_flags](#6383)
  - [--incompatible_disallow_data_transition](#6153)
  - [--incompatible_package_name_is_a_function](#5827)
  - [--incompatible_disallow_slash_operator](#5823)
  - [--incompatible_static_name_resolution](#5637)

Incompatible changes:

  - the --experimental_no_dotd_scanning_with_modules command line
    argument is not supported anymore.
  - The --prune_cpp_modules command line option is not supported
    anymore.
  - the --experimental_prune_cpp_input_discovery command line option
    is not supported anymore.

New features:

  - Added support for Android NDK r18.

Important changes:

  - The 'default' parameter of attr.output and attr.output_list is
    removed. This is controlled by
    --incompatible_no_output_attr_default
  - A number of platform-related Starlark APIs which were previously
    marked "experimental" are now disabled by default, and may be
    enabled via --experimental_platforms_api
  - Make legacy-test-support ("legacy_test-<api-level>") from
    android_sdk_repository neverlink. The legacy test support
    libraries shouldn't be built into test binaries. To make them
    available at runtime, developers should declare them via
    uses-library:
    https://developer.android.com/training/testing/set-up-project#andr
    oid-test-base
  - query remote server Capabilities (per REAPI v2)
  - CppRules: All cc_toolchains depended on from
    cc_toolchain_suite.toolchains are now analyzed when not using
    platforms in order to select the right cc_toolchain.
  - removed obsolete --explicit_jre_deps flag.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - Improve error messaging when unsupport proguard options are
    specified at the library level.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - The --incompatible_disable_late_bound_option_defaults flag has
    been flipped (#6384)
  - Incompatible flag
    --incompatible_disable_legacy_flags_cc_toolchain_api was flipped
    (#6434)
  - Fixed issue where ctx.resolve_command created conflicting
    intermediate files when resolve_command was called multiple times
    within the same rule invocation with a long command attribute.
  - Incompatible flag
    --incompatible_disable_cc_configuration_make_variables was
    flipped (#6381)
  - If the --javabase flag is unset, it Bazel locates a JDK using
    the JAVA_HOME environment variable and searching the PATH. If no
    JDK is found --javabase will be empty, and builds targeting Java
    will not
    be supported. Previously Bazel would fall back to using the
    embedded
    JDK as a --javabase, but this is no longer default behaviour. A
    JDK should
    be explicitly installed instead to enable Java development
  - Bazel will now shut down when idle for 5 minutes and the system
    is low on RAM (linux only).
  - CROSSTOOL file is now read from the package of cc_toolchain, not
    from
    the package of cc_toolchain_suite. This is not expected to break
    anybody since
    cc_toolchain_suite and cc_toolchain are commonly in the same
    package.
  - All overrides of Starlark's ctx.new_file function are now
    deprecated.
      Try the `--incompatible_new_actions_api` flag to ensure your
    code is forward-compatible.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - Introduce --(no)shutdown_on_low_sys_mem startup flag to toggle
    idle low-memory shutdown, disabled by default.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - CppRules: All cc_toolchains depended on from
    cc_toolchain_suite.toolchains are now analyzed when not using
    platforms in order to select the right cc_toolchain.
  - The function `attr.license` is deprecated and will be removed.
      It can be disabled now with `--incompatible_no_attr_license`.
  - `range()` function now returns a lazy value
    (`--incompatible_range_type` is now set by default).
  - The code coverage report now includes the actual paths to header
    files instead of the ugly,
    Bazel generated, virtual includes path.
  - `--incompatible_disallow_conflicting_providers` has been switched
    to true
  - Add new flag `--incompatible_disable_systool_from_configration` to
    disable loading the systool from CppConfiguration.
  - Add new flag `--incompatible_disable_sysroot_from_configuration`
    to
    disable loading the systool from CppConfiguration.
  - Sorting remote Platform properties for remote execution. May
    affect cache keys!
  - Use different server log files per Bazel server process; java.log
    is
    now a symlink to the latest log.

This release contains contributions from many people at Google, as well as a7g4 <a7g4@a7g4.net>, Alan <alan.agius@betssongroup.com>, Asaf Flescher <asafflesch@gmail.com>, Benjamin Peterson <bp@benjamin.pe>, Ed Schouten <ed.schouten@prodrive-technologies.com>, George Gensure <ggensure@uber.com>, George Kalpakas <kalpakas.g@gmail.com>, Greg <gregestren@users.noreply.github.com>, Irina Iancu <iirina@users.noreply.github.com>, Keith Smiley <keithbsmiley@gmail.com>, Loo Rong Jie <loorongjie@gmail.com>, Mark Zeren <mzeren@vmware.com>, Petros Eskinder <petroseskinder@users.noreply.github.com>, rachcatch <rachelcatchpoole@hotmail.com>, Robert Brown <robert.brown@gmail.com>, Robert Gay <robert.gay@redfin.com>, Salty Egg <2281521+zhouhao@users.noreply.github.com>.

bazel-io pushed a commit that referenced this issue Nov 30, 2018

Remove --incompatible_use_remotejdk_as_host_javabase flag.
Now we always use the remote JDK if host javabase is not explicitly set (and if
we need a JDK at all).

Progress on #6656 and #6592 and #6313.

RELNOTES: None
PiperOrigin-RevId: 223524214

ahirreddy pushed a commit to ahirreddy/bazel that referenced this issue Dec 1, 2018

Release 0.20.0 (2018-11-30)
Baseline: 7bf7f03

Cherry picks:

   + fd52341:
     update bazel-toolchains pin to latest release Part of changes to
     allow bazelci to use 0.19.0 configs. RBE toolchain configs at or
     before 0.17.0 are not compatible with bazel 0.19.0 or above.
   + 241f28d:
     Revert "Toggle --incompatible_disable_late_bound_option_defaults
     flag."
   + f7e5aef:
     Add cc_toolchain targets for the new entries in the default
     cc_toolchain_suite.
   + d2920e3:
     Revert "WindowsFileSystem: open files with delete-sharing"

[Breaking changes in 0.20](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Abreaking-change-0.20)

  - [--incompatible_remove_native_http_archive](bazelbuild#6570).
  - [--incompatible_remove_native_git_repository](bazelbuild#6569).
  - [--incompatible_disable_cc_toolchain_label_from_crosstool_proto](bazelbuild#6434).
  - [--incompatible_disable_depset_in_cc_user_flags](bazelbuild#6384).
  - [--incompatible_disable_cc_configuration_make_variables](bazelbuild#6381).
  - [--incompatible_disallow_conflicting_providers](bazelbuild#5902).
  - [--incompatible_range_type](bazelbuild#5264).

[0.20 is a migration window for the following changes](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Amigration-0.20)

  - [--incompatible_use_jdk10_as_host_javabase](bazelbuild#6661)
  - [--incompatible_use_remotejdk_as_host_javabase](bazelbuild#6656)
  - [--incompatible_disable_sysroot_from_configuration](bazelbuild#6565)
  - [--incompatible_provide_cc_toolchain_info_from_cc_toolchain_suite](bazelbuild#6537)
  - [--incompatible_disable_depset_in_cc_user_flags](bazelbuild#6383)
  - [--incompatible_package_name_is_a_function](bazelbuild#5827)

[Breaking changes in the next release (0.21)](https://github.com/bazelbuild/bazel/issues?q=is%3Aissue+label%3Abreaking-change-0.21)

  - [--incompatible_use_jdk10_as_host_javabase](bazelbuild#6661)
  - [--incompatible_use_remotejdk_as_host_javabase](bazelbuild#6656)
  - [--incompatible_disable_sysroot_from_configuration](bazelbuild#6565)
  - [--incompatible_provide_cc_toolchain_info_from_cc_toolchain_suite](bazelbuild#6537)
  - [--incompatible_disable_depset_in_cc_user_flags](bazelbuild#6383)
  - [--incompatible_disallow_data_transition](bazelbuild#6153)
  - [--incompatible_package_name_is_a_function](bazelbuild#5827)
  - [--incompatible_disallow_slash_operator](bazelbuild#5823)
  - [--incompatible_static_name_resolution](bazelbuild#5637)

Incompatible changes:

  - the --experimental_no_dotd_scanning_with_modules command line
    argument is not supported anymore.
  - The --prune_cpp_modules command line option is not supported
    anymore.
  - the --experimental_prune_cpp_input_discovery command line option
    is not supported anymore.

New features:

  - Added support for Android NDK r18.

Important changes:

  - The 'default' parameter of attr.output and attr.output_list is
    removed. This is controlled by
    --incompatible_no_output_attr_default
  - A number of platform-related Starlark APIs which were previously
    marked "experimental" are now disabled by default, and may be
    enabled via --experimental_platforms_api
  - Make legacy-test-support ("legacy_test-<api-level>") from
    android_sdk_repository neverlink. The legacy test support
    libraries shouldn't be built into test binaries. To make them
    available at runtime, developers should declare them via
    uses-library:
    https://developer.android.com/training/testing/set-up-project#andr
    oid-test-base
  - query remote server Capabilities (per REAPI v2)
  - CppRules: All cc_toolchains depended on from
    cc_toolchain_suite.toolchains are now analyzed when not using
    platforms in order to select the right cc_toolchain.
  - removed obsolete --explicit_jre_deps flag.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - Improve error messaging when unsupport proguard options are
    specified at the library level.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - Incompatible flag
    --incompatible_disable_legacy_cpp_toolchain_skylark_api was
    flipped.
  - The --incompatible_disable_late_bound_option_defaults flag has
    been flipped (bazelbuild#6384)
  - Incompatible flag
    --incompatible_disable_legacy_flags_cc_toolchain_api was flipped
    (bazelbuild#6434)
  - Fixed issue where ctx.resolve_command created conflicting
    intermediate files when resolve_command was called multiple times
    within the same rule invocation with a long command attribute.
  - Incompatible flag
    --incompatible_disable_cc_configuration_make_variables was
    flipped (bazelbuild#6381)
  - If the --javabase flag is unset, it Bazel locates a JDK using
    the JAVA_HOME environment variable and searching the PATH. If no
    JDK is found --javabase will be empty, and builds targeting Java
    will not
    be supported. Previously Bazel would fall back to using the
    embedded
    JDK as a --javabase, but this is no longer default behaviour. A
    JDK should
    be explicitly installed instead to enable Java development
  - Bazel will now shut down when idle for 5 minutes and the system
    is low on RAM (linux only).
  - CROSSTOOL file is now read from the package of cc_toolchain, not
    from
    the package of cc_toolchain_suite. This is not expected to break
    anybody since
    cc_toolchain_suite and cc_toolchain are commonly in the same
    package.
  - All overrides of Starlark's ctx.new_file function are now
    deprecated.
      Try the `--incompatible_new_actions_api` flag to ensure your
    code is forward-compatible.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - Introduce --(no)shutdown_on_low_sys_mem startup flag to toggle
    idle low-memory shutdown, disabled by default.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - --incompatible_disable_cc_toolchain_label_from_crosstool_proto
    was flipped.
  - CppRules: All cc_toolchains depended on from
    cc_toolchain_suite.toolchains are now analyzed when not using
    platforms in order to select the right cc_toolchain.
  - The function `attr.license` is deprecated and will be removed.
      It can be disabled now with `--incompatible_no_attr_license`.
  - `range()` function now returns a lazy value
    (`--incompatible_range_type` is now set by default).
  - The code coverage report now includes the actual paths to header
    files instead of the ugly,
    Bazel generated, virtual includes path.
  - `--incompatible_disallow_conflicting_providers` has been switched
    to true
  - Add new flag `--incompatible_disable_systool_from_configration` to
    disable loading the systool from CppConfiguration.
  - Add new flag `--incompatible_disable_sysroot_from_configuration`
    to
    disable loading the systool from CppConfiguration.
  - Sorting remote Platform properties for remote execution. May
    affect cache keys!
  - Use different server log files per Bazel server process; java.log
    is
    now a symlink to the latest log.

This release contains contributions from many people at Google, as well as a7g4 <a7g4@a7g4.net>, Alan <alan.agius@betssongroup.com>, Asaf Flescher <asafflesch@gmail.com>, Benjamin Peterson <bp@benjamin.pe>, Ed Schouten <ed.schouten@prodrive-technologies.com>, George Gensure <ggensure@uber.com>, George Kalpakas <kalpakas.g@gmail.com>, Greg <gregestren@users.noreply.github.com>, Irina Iancu <iirina@users.noreply.github.com>, Keith Smiley <keithbsmiley@gmail.com>, Loo Rong Jie <loorongjie@gmail.com>, Mark Zeren <mzeren@vmware.com>, Petros Eskinder <petroseskinder@users.noreply.github.com>, rachcatch <rachelcatchpoole@hotmail.com>, Robert Brown <robert.brown@gmail.com>, Robert Gay <robert.gay@redfin.com>, Salty Egg <2281521+zhouhao@users.noreply.github.com>.
@Monnoroch

This comment has been minimized.

Copy link

Monnoroch commented Dec 6, 2018

@davido probably better to include bazel sync.

@scottmin0r

This comment has been minimized.

Copy link

scottmin0r commented Dec 17, 2018

Philosophical question - why is the default behavior (after the flag is flipped) to download from a remote repository, unless this is opted out by specifying --host_javabase=@local_jdk//:jdk? This might be convenient for some use cases, but it has some drawbacks:

  • The version of the JDK used is effectively hardcoded into bazel; future bazel versions can bump the JDK version, forcing users to effectively update JDK versions on bazel's schedule rather than their own
  • (the one I care more about) bazel now (possibly) has a build-time dependency on an external system with no corresponding WORKSPACE entry to audit

From the above linked doc, one of the reasons for doing this is:

It will align how we handle toolchains for different languages (e.g. Bazel doesn’t come with a C++ compiler).

By default, bazel doesn't download a C++ compiler from the internet at build time, either (I hope!) unless you have the WORKSPACE entries to explicitly do exactly that. Why should the Java toolchain be any different?

@davido

This comment has been minimized.

Copy link
Contributor

davido commented Dec 17, 2018

Why should the Java toolchain be any different?

Is this because Java tool chain is patched by Bazel team to support JavaBuilder's additional features? If you build with vanilla java builder then these features would be lost:

# The 'vanilla' toolchain is an unsupported alternative to the default.
#
# It does not provider any of the following features:
#   * Error Prone
#   * Strict Java Deps
#   * Header Compilation
#   * Reduced Classpath Optimization
@scottmin0r

This comment has been minimized.

Copy link

scottmin0r commented Dec 21, 2018

Ok, I can see how the default no-flag behavior is helpful to Java developers - they get the fully-featured toolchain with no configuration.

However, this change feels hostile to organizations that attempt to control their third-party dependencies (on both code and systems). Bazel has a mechanism for requesting third-party artifacts that is auditable - the WORKSPACE file. The fact that something outside of the WORKSPACE file gets downloaded by default is troubling, because now auditing third-party artifacts and systems the build is dependent on is a non-trivial task.

@meisterT

This comment has been minimized.

Copy link
Member

meisterT commented Dec 22, 2018

Scott, if you're worried about the download, just set the host_javabase explicitly, e.g. to something vendored or the local jdk.

@davido

This comment has been minimized.

Copy link
Contributor

davido commented Dec 23, 2018

Scott, if you're worried about the download, just set the host_javabase explicitly, e.g. to something vendored or the local jdk.

+1. Today Bazel still doesn't support Java 11 as target java version on their default toolchain (sadly). However, check this Gerrit instruction how one can still produce Java 11 byte code with Bazel using vanilla build tool chain. But note, that all those neat features I mentioned above would be lost:

$ bazel build \
    --define=ABSOLUTE_JAVABASE=/usr/lib64/jvm/jre-11-openjdk \
    --host_javabase=@bazel_tools//tools/jdk:absolute_javabase \
    --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
    --java_toolchain=@bazel_tools//tools/jdk:toolchain_vanilla \
    :release
@scottmin0r

This comment has been minimized.

Copy link

scottmin0r commented Dec 26, 2018

Scott, if you're worried about the download, just set the host_javabase explicitly, e.g. to something vendored or the local jdk.

Yes, that is the current path forward for me. Thanks for documenting the workaround here, so that I know what to do.

I'm trying to say that this change, while it has convenient default behavior for some use cases, is surprising as well. All our other toolchains (C++, Go, protobuf) use locally-installed components; if there are downloads, those are set up via Starlark in the WORKSPACE file, which requires project owners to opt-in to downloads and consequently the systems they download from. Bazel has not, as far as I know, downloaded extra non-WORKSPACE-specified artifacts during the build, until now (please correct me if I'm wrong!). Teams that are not paying attention to these updates and flag-flips just got opted-in to a build-time dependency on external packages and systems. This is important to orgs that have strict policies around such things.

I'd prefer to see a change where the default behavior is a non-downloading one. I'd prefer that some amount of Starlark be inserted in the WORKSPACE file to trigger this remotejdk download (even if it's a one-liner). To my knowledge, this is how all other toolchains must do things. I'd be curious to know if there's a technical reason why Java can't follow the same pattern, or what the rationale for this usability tradeoff is here.

BUT - at the end of the day, this isn't my project; this is just one user's perspective. I do appreciate your time and development effort.

@meisterT

This comment has been minimized.

Copy link
Member

meisterT commented Jan 7, 2019

Scott, thanks for your feedback. This also might be the direction in which we will be moving for Java.

Instead of coupling the steps together we decided to do baby steps (same JDK version as before etc) to break as few people as possible.

@SimonBoorer

This comment has been minimized.

Copy link

SimonBoorer commented Jan 18, 2019

This change prevents bootstrapping 0.21.0 without network access unless you set host_javabase explicitly (e.g. --host_javabase=@local_jdk//:jdk). It would be good if this was documented in the compilation instructions, but also this seems contradictory to the stance taken with @desugar_jdk_libs in #5202.

@meisterT

This comment has been minimized.

Copy link
Member

meisterT commented Jan 18, 2019

Simon, thanks for reporting. We have a couple of options how to fix that:
a) document to set EXTRA_BAZEL_ARGS if you want to build without network
b) include the remote JDKs in the bazel dist archive
c) explicitly set --host_javabase to the local_jdk (so it can be overridden by the user, but defaults to it). We require a JDK to be installed anyway.

Any preferences from your side?
cc @aehlig who spent some time working on bootstrapping w/o network.

@meisterT meisterT reopened this Jan 18, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment