# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Map run
description: Run a command on multiple paths.

inputs:
  command:
    description: The command to run.
    required: true
  paths:
    description: A JSON list of paths to run the command on.
    required: true
  outputs-always:
    description: Show command outputs whether or not it fails.
    required: false
    default: "false"

runs:
  using: composite
  steps:
    - name: Run command
      uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
      with:
        script: |
          const { spawnSync } = await import("node:child_process");

          const cmd = "${{ inputs.command }}";
          const paths = ${{ inputs.paths }};
          if (paths.length === 0) {
            console.log("Nothing to do.");
          }
          const outputsAlways = ${{ inputs.outputs-always }};

          let failed = [];
          for (const path of paths) {
            let stdout = "";
            let stderr = "";
            try {
              const p = spawnSync("bash", ["-c", cmd], {cwd: path});
              console.log(`✅ [${path}]: ${cmd}`);
              stdout = p.stdout && p.stdout.toString("utf8");
              stderr = p.stderr && p.stderr.toString("utf8");
            } catch (e) {
              failed.push(path);
              console.log(`❌ [${path}]: ${cmd} (exit code ${e.status})`);
              core.error(e.message);
              stdout = e.stdout && e.stdout.toString("utf8");
              stderr = e.stderr && e.stderr.toString("utf8");
            }
            if (outputsAlways || failed.includes(path)) {
              console.log('---- stdout ----');
              console.log(stdout || "");
              console.log('---- stderr ----');
              console.log(stderr || "");
            }
          }
          console.log("=== Summary ===");
          console.log(`  Passed: ${paths.length - failed.length}`);
          console.log(`  Failed: ${failed.length}`);
          if (failed.length > 0) {
            core.setFailed(`Failed '${cmd}' on: ${failed.join(', ')}`);
          }

