diff --git a/README.md b/README.md index 1a4fc23..a60a3e5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# merge-action +# nx-action Hosts the code for the [Trunk Merge Queue](https://docs.trunk.io/merge-queue) GitHub Action, which makes it easy to upload the required impacted targets for PRs when running your merge queues in @@ -95,9 +95,9 @@ share an impacted target must be tested together; otherwise, they can be tested ## Under the hood -We use the Nx CLI to create a dependency graph that shows all of the affected libraries from the -pull request. More information on the command can be found -[here](https://nx.dev/nx-api/nx/documents/dep-graph) +We use the Nx CLI to show all affected projects betweent the current branch and the tip of main. +More information on the command +[can be found here](https://nx.dev/nx-api/nx/documents/show#affected) ## Questions diff --git a/action.yaml b/action.yaml index a965afa..33a7263 100644 --- a/action.yaml +++ b/action.yaml @@ -17,7 +17,7 @@ inputs: required: false workspace-path: description: Path to your Nx workspace. If none is provided, will use the root directory. - required: true + required: false impact-all-filters-path: description: A path to a list of filters to identify whether `ALL` impacted targets should be considered. @@ -60,7 +60,7 @@ runs: - name: Compute Impacted Targets if: ${{ steps.prerequisites.outputs.impacts_all_detected == 'false' }} id: compute-impacted-targets - working-directory: ${{ inputs.workspace-path }} + working-directory: ${{ inputs.workspace-path || '.' }} run: python ${GITHUB_ACTION_PATH}/src/compute_impacted_targets.py shell: bash env: @@ -73,7 +73,7 @@ runs: - name: Upload Impacted Targets id: upload-impacted-targets - working-directory: ${{ inputs.workspace-path }} + working-directory: ${{ inputs.workspace-path || '.' }} run: python ${GITHUB_ACTION_PATH}/src/upload_impacted_targets.py shell: bash env: diff --git a/src/compute_impacted_targets.py b/src/compute_impacted_targets.py index 63f105a..6e1aae3 100644 --- a/src/compute_impacted_targets.py +++ b/src/compute_impacted_targets.py @@ -1,4 +1,3 @@ -import json import os from utils import ( @@ -27,33 +26,29 @@ def log_if_verbose(log=""): # Get the list of impacted targets by leveraging Nx's dependency graph capabilities. # https://nx.dev/nx-api/nx/documents/dep-graph -affected_json_out = f"./{merge_instance_branch_head_sha}_{pr_branch_head_sha}.json" -nx_graph_command_base = f"npx nx graph --affected --verbose --base={merge_instance_branch_head_sha} --head={pr_branch_head_sha}" -graph_output = run_command( - f"{nx_graph_command_base} --file={affected_json_out}", verbose=verbose -) -log_if_verbose(graph_output) - -affected_json = json.loads(run_command(f"cat {affected_json_out}", return_output=True)) +affected_list_out = f"./{merge_instance_branch_head_sha}_{pr_branch_head_sha}.txt" +nx_show_command_base = f"npx nx show projects --affected --base={merge_instance_branch_head_sha} --head={pr_branch_head_sha}" +affected_output = run_command(nx_show_command_base, verbose=verbose, return_output=True) -impacted_projects = ( - affected_json["affectedProjects"] if "affectedProjects" in affected_json else [] -) print(f"Impacted projects are:") -print(*impacted_projects, sep=",\n") +print(affected_output) + +affected_projects = [] +if affected_output: + affected_projects = affected_output.split("\n") # Move this to a file so we can pass it to the next action, as this list # can be rather large. impacted_targets_out = f"./{merge_instance_branch_head_sha}" with open(impacted_targets_out, "w", encoding="utf-8") as f: - f.write(f"{impacted_projects}") + f.write(f"{affected_output}") -num_impacted_projects = len(impacted_projects) +num_impacted_projects = len(affected_projects) print( f"Computed {num_impacted_projects} impacted projects for sha {pr_branch_head_sha}" ) -print(f"To replicate this command, run the following:\n{nx_graph_command_base}\n") +print(f"To replicate this command, run the following:\n{nx_show_command_base}\n") # Outputs github_output = f"impacted_targets_out={impacted_targets_out}\n" diff --git a/src/prerequisites.py b/src/prerequisites.py index 93c5a64..807d6c7 100644 --- a/src/prerequisites.py +++ b/src/prerequisites.py @@ -35,6 +35,8 @@ def fetch_remote_git_history(ref): print("No merge instance branch found. Exiting.") sys.exit(1) +write_to_github_output(f"merge_instance_branch={merge_instance_branch}") + # Check if any file specified by the filters in impact-all-filters-path was # changed in the PR. If it was, then mark this PR as impacting all other PRs. impacts_filters_changes = os.environ.get("IMPACTS_FILTERS_CHANGES") @@ -59,7 +61,6 @@ def fetch_remote_git_history(ref): print("Could not identify merge instance branch head sha") sys.exit(1) -github_output = f"merge_instance_branch={merge_instance_branch}\nmerge_instance_branch_head_sha={merge_instance_branch_head_sha}\nimpacts_all_detected=false" -log_if_verbose(f"Setting these outputs:\n{github_output}") +github_output = f"merge_instance_branch_head_sha={merge_instance_branch_head_sha}\nimpacts_all_detected=false" write_to_github_output(github_output) diff --git a/src/upload_impacted_targets.py b/src/upload_impacted_targets.py index c62a9b5..7880430 100644 --- a/src/upload_impacted_targets.py +++ b/src/upload_impacted_targets.py @@ -1,4 +1,3 @@ -import ast import json import os import sys @@ -9,7 +8,7 @@ verbose = get_bool_from_string(os.environ.get("VERBOSE")) -IMPACTS_ALL_KEYWORD = "IMPACTS_ALL" +IMPACTS_ALL_KEYWORD = "ALL" def log_if_verbose(log=""): @@ -51,7 +50,7 @@ def log_if_verbose(log=""): pr_number = get_and_require_env_var("PR_NUMBER") pr_branch_head_sha = get_and_require_env_var("PR_BRANCH_HEAD_SHA") -IMPACTED_TARGETS = "" +IMPACTED_TARGETS: str | list[str] = "" impacts_all_detected = get_bool_from_string( get_and_require_env_var("IMPACTS_ALL_DETECTED") ) @@ -60,7 +59,11 @@ def log_if_verbose(log=""): else: impacted_targets_file = get_and_require_env_var("IMPACTED_TARGETS_FILE") with open(impacted_targets_file, "r", encoding="utf-8") as f: - IMPACTED_TARGETS = ast.literal_eval(f.read()) + content = f.read().strip() + if not content: + IMPACTED_TARGETS = [] + else: + IMPACTED_TARGETS = content.split("\n") log_if_verbose(f"Read impacted targets: {IMPACTED_TARGETS}") diff --git a/src/utils.py b/src/utils.py index 9951588..7d605af 100644 --- a/src/utils.py +++ b/src/utils.py @@ -51,4 +51,4 @@ def get_bool_from_string(bool_string): def write_to_github_output(github_output): with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f: - f.write(github_output) + f.write(f"{github_output}\n")