From 9546dd1e26df6f337b9d7e5e59bfabb6465884e3 Mon Sep 17 00:00:00 2001 From: vindard <17693119+vindard@users.noreply.github.com> Date: Tue, 17 Oct 2023 13:55:26 -0400 Subject: [PATCH 1/5] feat: add unit test to buck --- core/api/BUCK | 10 ++ toolchains/workspace-pnpm/macros.bzl | 131 +++++++++++++++++++++++++++ 2 files changed, 141 insertions(+) diff --git a/core/api/BUCK b/core/api/BUCK index a3179e0949..52f001e3e9 100644 --- a/core/api/BUCK +++ b/core/api/BUCK @@ -10,6 +10,7 @@ load( "typescript_check", "yaml_check", "madge_check", + "test_unit", ) load("@toolchains//rover:macros.bzl", "sdl", "diff_check", "dev_update_file") @@ -155,6 +156,15 @@ madge_check( srcs = [":src"], ) +test_unit( + name = "unit-tests", + srcs = [":src"] + [":test_src"] + glob["galoy.yaml"], + config_file = "test/unit/jest.config.js", + env = { + "LOGLEVEL": "warn", + } +) + test_suite( name = "test-unit", tests = [ diff --git a/toolchains/workspace-pnpm/macros.bzl b/toolchains/workspace-pnpm/macros.bzl index bf40792efd..794be64ff3 100644 --- a/toolchains/workspace-pnpm/macros.bzl +++ b/toolchains/workspace-pnpm/macros.bzl @@ -603,6 +603,8 @@ def _npm_test_impl( ExternalRunnerTestInfo( type = test_info_type, command = [run_cmd_args], + env = ctx.attrs.env, + labels = ctx.attrs.labels, ), ) + [ DefaultInfo(default_output = args_file), @@ -723,6 +725,18 @@ _eslint = rule( "node_modules": attrs.source( doc = """Target which builds `node_modules`.""", ), + "env": attrs.dict( + key = attrs.string(), + value = attrs.arg(), + sorted = False, + default = {}, + doc = """Set environment variables for this rule's invocation of eslint. The environment + variable values may include macros which are expanded.""", + ), + "labels": attrs.list( + attrs.string(), + default = [], + ), "_inject_test_env": attrs.default_only( attrs.dep(default = "prelude//test/tools:inject_test_env"), ), @@ -791,6 +805,18 @@ _typescript_check = rule( "node_modules": attrs.source( doc = """Target which builds package `node_modules`.""", ), + "env": attrs.dict( + key = attrs.string(), + value = attrs.arg(), + sorted = False, + default = {}, + doc = """Set environment variables for this rule's invocation of tsc. The environment + variable values may include macros which are expanded.""", + ), + "labels": attrs.list( + attrs.string(), + default = [], + ), "_inject_test_env": attrs.default_only( attrs.dep(default = "prelude//test/tools:inject_test_env"), ), @@ -854,6 +880,18 @@ _yaml_check = rule( "node_modules": attrs.source( doc = """Target which builds package `node_modules`.""", ), + "env": attrs.dict( + key = attrs.string(), + value = attrs.arg(), + sorted = False, + default = {}, + doc = """Set environment variables for this rule's invocation of prettier. The environment + variable values may include macros which are expanded.""", + ), + "labels": attrs.list( + attrs.string(), + default = [], + ), "_inject_test_env": attrs.default_only( attrs.dep(default = "prelude//test/tools:inject_test_env"), ), @@ -919,6 +957,18 @@ _madge_check = rule( "node_modules": attrs.source( doc = """Target which builds package `node_modules`.""", ), + "env": attrs.dict( + key = attrs.string(), + value = attrs.arg(), + sorted = False, + default = {}, + doc = """Set environment variables for this rule's invocation of madge. The environment + variable values may include macros which are expanded.""", + ), + "labels": attrs.list( + attrs.string(), + default = [], + ), "_inject_test_env": attrs.default_only( attrs.dep(default = "prelude//test/tools:inject_test_env"), ), @@ -1006,3 +1056,84 @@ dev_pnpm_task_test = rule(impl = pnpm_task_test_impl, attrs = { "srcs": attrs.list(attrs.source(), default = [], doc = """List of sources we require"""), "deps": attrs.list(attrs.source(), default = [], doc = """List of dependencies we require"""), }) + +def test_unit_impl(ctx: AnalysisContext) -> list[[ + DefaultInfo, + RunInfo, + ExternalRunnerTestInfo, +]]: + args = cmd_args() + args.add("--config") + args.add(ctx.attrs.config_file) + args.add("--bail") + args.add("--verbose") + + return _npm_test_impl( + ctx, + ctx.attrs.jest[RunInfo], + args, + "jest", + ) + +_test_unit = rule( + impl = test_unit_impl, + attrs = { + "srcs": attrs.list( + attrs.source(), + default = [], + doc = """List of package source files to track.""", + ), + "jest": attrs.dep( + providers = [RunInfo], + doc = """jest dependency.""", + ), + "config_file": attrs.option( + attrs.string(), + doc = """File name and relative path for jest config.""", + ), + "env": attrs.dict( + key = attrs.string(), + value = attrs.arg(), + sorted = False, + default = {}, + doc = """Set environment variables for this rule's invocation of jest. The environment + variable values may include macros which are expanded.""", + ), + "labels": attrs.list( + attrs.string(), + default = [], + ), + "node_modules": attrs.source( + doc = """Target which builds package `node_modules`.""", + ), + "_inject_test_env": attrs.default_only( + attrs.dep(default = "prelude//test/tools:inject_test_env"), + ), + "_python_toolchain": attrs.toolchain_dep( + default = "toolchains//:python", + providers = [PythonToolchainInfo], + ), + "_workspace_pnpm_toolchain": attrs.toolchain_dep( + default = "toolchains//:workspace_pnpm", + providers = [WorkspacePnpmToolchainInfo], + ), + }, +) + +def test_unit( + node_modules = ":node_modules", + visibility = ["PUBLIC"], + **kwargs): + jest_bin = "jest_bin" + if not rule_exists(jest_bin): + npm_bin( + name = jest_bin, + bin_name = "jest", + ) + + _test_unit( + jest = ":{}".format(jest_bin), + node_modules = node_modules, + visibility = visibility, + **kwargs, + ) From a7437a88eb68ecfb847181526e7ee2621f963f43 Mon Sep 17 00:00:00 2001 From: vindard <17693119+vindard@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:38:26 -0400 Subject: [PATCH 2/5] chore: and .env file to unit test buck run --- core/api/BUCK | 3 ++- toolchains/workspace-pnpm/macros.bzl | 12 ++++++++++-- toolchains/workspace-pnpm/run_in_dir.py | 22 +++++++++++++++++----- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/core/api/BUCK b/core/api/BUCK index 52f001e3e9..aa4183e580 100644 --- a/core/api/BUCK +++ b/core/api/BUCK @@ -158,8 +158,9 @@ madge_check( test_unit( name = "unit-tests", - srcs = [":src"] + [":test_src"] + glob["galoy.yaml"], + srcs = [":src"] + [":test_src"] + glob([".env", "galoy.yaml"]), config_file = "test/unit/jest.config.js", + env_file = ".env", env = { "LOGLEVEL": "warn", } diff --git a/toolchains/workspace-pnpm/macros.bzl b/toolchains/workspace-pnpm/macros.bzl index 794be64ff3..878748bb49 100644 --- a/toolchains/workspace-pnpm/macros.bzl +++ b/toolchains/workspace-pnpm/macros.bzl @@ -592,10 +592,14 @@ def _npm_test_impl( cmd_args([build_context.workspace_root, ctx.label.package], delimiter = "/"), "--bin", cmd_args(program_run_info), - "--", - program_args, ]) + if hasattr(ctx.attrs, 'env_file'): + run_cmd_args.add("--env-file") + run_cmd_args.add(ctx.attrs.env_file) + + run_cmd_args.add("--") + run_cmd_args.add(program_args) args_file = ctx.actions.write("args.txt", run_cmd_args) return inject_test_run_info( @@ -1091,6 +1095,10 @@ _test_unit = rule( attrs.string(), doc = """File name and relative path for jest config.""", ), + "env_file": attrs.option( + attrs.string(), + doc = """File name and relative path for env variables required.""", + ), "env": attrs.dict( key = attrs.string(), value = attrs.arg(), diff --git a/toolchains/workspace-pnpm/run_in_dir.py b/toolchains/workspace-pnpm/run_in_dir.py index da6ce99d3d..60e4fd8a01 100644 --- a/toolchains/workspace-pnpm/run_in_dir.py +++ b/toolchains/workspace-pnpm/run_in_dir.py @@ -3,16 +3,23 @@ Runs a program in a directory. """ import argparse +import json import os import subprocess import sys -def compute_path(arg: str) -> str: - if arg.endswith("::abspath"): - return os.path.abspath(arg.removesuffix("::abspath")) +def merge_env_from_file(file_path): + # Shell command to source the .env file and then get the environment as JSON using jq + if file_path and os.path.exists(file_path): + cmd = f'source {file_path} && jq -n env' else: - return arg + cmd = f'jq -n env' + result = subprocess.run(cmd, capture_output=True, text=True, shell=True, executable="/bin/bash") + if result.returncode != 0: + raise RuntimeError(result.stderr) + + return json.loads(result.stdout) if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) @@ -24,6 +31,10 @@ def compute_path(arg: str) -> str: "--bin", help="Binary to execute program with", ) + parser.add_argument( + "--env-file", + help="Env file to load variables from", + ) parser.add_argument( "args", help="Program and arguments", @@ -34,6 +45,7 @@ def compute_path(arg: str) -> str: bin_args = args.args[1:] # ignore '--' separator cmd = [os.path.abspath(args.bin), *bin_args] - exit_code = subprocess.call(cmd, cwd=args.cwd) + env = merge_env_from_file(args.env_file) + exit_code = subprocess.call(cmd, cwd=args.cwd, env=env) sys.exit(exit_code) From 3e98c8b94392d10ed504e9d0b56a4bd70738fdb9 Mon Sep 17 00:00:00 2001 From: vindard <17693119+vindard@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:52:35 -0400 Subject: [PATCH 3/5] chore: add unit tests to 'test_suite' --- core/api/BUCK | 1 + 1 file changed, 1 insertion(+) diff --git a/core/api/BUCK b/core/api/BUCK index aa4183e580..1b6c7462e8 100644 --- a/core/api/BUCK +++ b/core/api/BUCK @@ -176,5 +176,6 @@ test_suite( ":check-circular-dependencies", ":public-schema-diff", ":admin-schema-diff", + ":unit-tests", ], ) From 6eac5741fcc11e4ccee8336156a06fae7083fbf0 Mon Sep 17 00:00:00 2001 From: vindard <17693119+vindard@users.noreply.github.com> Date: Fri, 17 Nov 2023 11:19:15 -0400 Subject: [PATCH 4/5] refactor: remove jq and handle env in python --- toolchains/workspace-pnpm/run_in_dir.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/toolchains/workspace-pnpm/run_in_dir.py b/toolchains/workspace-pnpm/run_in_dir.py index 60e4fd8a01..b2fa463626 100644 --- a/toolchains/workspace-pnpm/run_in_dir.py +++ b/toolchains/workspace-pnpm/run_in_dir.py @@ -3,23 +3,28 @@ Runs a program in a directory. """ import argparse -import json import os import subprocess import sys def merge_env_from_file(file_path): - # Shell command to source the .env file and then get the environment as JSON using jq + # Shell command to source the .env file if file_path and os.path.exists(file_path): - cmd = f'source {file_path} && jq -n env' + cmd = f'source {file_path} && env' else: - cmd = f'jq -n env' + cmd = f'env' result = subprocess.run(cmd, capture_output=True, text=True, shell=True, executable="/bin/bash") if result.returncode != 0: raise RuntimeError(result.stderr) - return json.loads(result.stdout) + lines = result.stdout.strip().split('\n') + env_dict = {} + for line in lines: + key, value = line.split('=', 1) + env_dict[key] = value + + return env_dict if __name__ == "__main__": parser = argparse.ArgumentParser(description=__doc__) From d2fdd9ce66acaa4186f7edb962288990553a4ddb Mon Sep 17 00:00:00 2001 From: vindard <17693119+vindard@users.noreply.github.com> Date: Fri, 17 Nov 2023 11:26:37 -0400 Subject: [PATCH 5/5] build: remove unit-test run from github actions --- .github/workflows/unit-test.yml | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 .github/workflows/unit-test.yml diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml deleted file mode 100644 index 6e573059c1..0000000000 --- a/.github/workflows/unit-test.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: "Unit test" - -on: - pull_request: - branches: [main] - -jobs: - unit-test: - name: Unit test - runs-on: ubuntu-latest - steps: - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@v4 - - name: Run the Magic Nix Cache - uses: DeterminateSystems/magic-nix-cache-action@v2 - - uses: actions/checkout@v3 - - run: cd core/api && nix develop -c pnpm install --frozen-lockfile - - name: Run unit tests - run: cd core/api && nix develop -c make unit-in-ci