Toolkit: Action exits early without completing

Created on 17 Oct 2019  路  5Comments  路  Source: actions/toolkit

I'm using the action toolkit to re-write an action of mine, and I'm having a hard time getting it to complete the processes within it. The action essentially deploys to a GitHub pages branch, and requires running a number of git commands. For this I've used @actions/exec and wrapped it in a function so I can more easily set the cwd. You can see an example of this below:

import { exec } from "@actions/exec";

export async function execute(cmd: string, cwd: string): Promise<String> {
  return new Promise((resolve, reject) => {
    exec(cmd, [], {
      cwd, 
      listeners: {
        stdout: (data: Buffer) => {
          resolve(data.toString().trim());
        },
        stderr: (data: Buffer) => {
          reject(data.toString().trim());
        }
      }
    });
  });
}

The problem I'm having is that my function doesn't seem to finish executing the commands before exiting. You can see a log here (it's the Build & Deploy step).

it seems to only get to the second command and then passes and I'm not entirely sure why. You can see the code for this here: https://github.com/JamesIves/github-pages-deploy-action/blob/rewrite/src/git.ts#L26-L28

The entrypoint which runs this looks like this, and you'll see in the logs that the Deployment Successful message never shows.

import * as core from "@actions/core";
import { init, deploy } from "./git";

async function run() {
  try {
    // Initializes the action.
    const action = await init();
    await deploy(action);
  } catch (error) {
    core.setFailed(error.message);
  } finally {
    console.log("Deployment Successful");
  }
}

run();

Is there an issue with how I'm awaiting these commands? It feels like I'm making a rookie mistake.

question

All 5 comments

Hey @JamesIves,

I think you need to await the exec inside your execute function, since it's async.

Possibly something like:

export async function execute(cmd: string, cwd: string): Promise<String> {
  return new Promise(async (resolve, reject) => {
    await exec(cmd, [], {
      cwd,
      listeners: {
        stdout: (data: Buffer) => {
          resolve(data.toString().trim());
        },
        stderr: (data: Buffer) => {
          reject(data.toString().trim());
        }
      }
    });
  });
}

or

export async function execute(cmd: string, cwd: string): Promise<String> {
  let myOutput = '';
  let myError = '';
  await exec(cmd, [], {
    cwd,
    listeners: {
      stdout: (data: Buffer) => {
        myOutput += data.toString().trim();
      },
      stderr: (data: Buffer) => {
        myError += data.toString().trim();
      }
    }
  });

  if (myError) {
    throw new Error(myError);
  }
  return myOutput;
}

Based on https://github.com/actions/toolkit/tree/master/packages/exec#outputoptions

Let me know if that helps!

Also, why are you wrapping exec with your own execute function? simply await exec.

I think Josh answered.

Yes, sorry I forgot to reply. @joshmgross solution worked for me.

Thanks for confirming.

Was this page helpful?
0 / 5 - 0 ratings