Skip to content

Commit

Permalink
Auto merge pull request #338 from atomist/automation-client-ts
Browse files Browse the repository at this point in the history
Move scripts to bin directory
  • Loading branch information
atomist-bot authored Aug 17, 2018
2 parents 231e5fa + d546885 commit 3a61594
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 0 deletions.
112 changes: 112 additions & 0 deletions src/bin/command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env node
/*
* Copyright © 2018 Atomist, Inc.
*
* See LICENSE file.
*/

process.env.SUPPRESS_NO_CONFIG_WARNING = "true";

import * as stringify from "json-stringify-safe";

import { automationClient } from "../automationClient";
import {
Configuration,
loadConfiguration,
} from "../configuration";
import { HandlerContext } from "../HandlerContext";
import { CommandInvocation } from "../internal/invoker/Payload";
import { consoleMessageClient } from "../internal/message/ConsoleMessageClient";
import { LoggingConfig } from "../internal/util/logger";
import { guid } from "../internal/util/string";
import { enableDefaultScanning } from "../scan";
import { AutomationServer } from "../server/AutomationServer";

LoggingConfig.format = "cli";

main();

/**
* Parse command line CommandInvocation argument, set up, and call the
* command handler. This method will not return.
*/
async function main() {
if (!process.argv[2]) {
console.error(`[ERROR] Missing command, you must supply the CommandInvocation on the command line`);
process.exit(3);
}
if (process.argv.length > 3) {
console.warn(`[WARN] Extra command line arguments will be ignored: ${process.argv.slice(3).join(" ")}`);
}
const ciString = process.argv[2];
try {
const ci: CommandInvocation = JSON.parse(ciString);
const configuration = await loadConfiguration();
enableDefaultScanning(configuration);
const node = automationClient(configuration);
await invokeOnConsole(node.automationServer, ci, createHandlerContext(configuration));
} catch (e) {
console.error(`[ERROR] Unhandled exception: ${e.message}`);
process.exit(101);
}
console.error(`[ERROR] Illegal state: unhandled execution path`);
process.exit(99);
}

/**
* Create a simple handler context for running command handlers from
* the command line.
*/
function createHandlerContext(config: Configuration): HandlerContext {
return {
workspaceId: config.workspaceIds[0],
correlationId: guid(),
messageClient: consoleMessageClient,
};
}

/**
* Run a command handler on the command line. This function will not
* return.
*
* @param automationServer automation server with the command
* @param ci command and its parameters
* @param ctx suitable execution context
*/
async function invokeOnConsole(automationServer: AutomationServer, ci: CommandInvocation, ctx: HandlerContext) {

// Set up the parameter, mappend parameters and secrets
const handler = automationServer.automations.commands.find(c => c.name === ci.name);
if (!handler) {
const commands = automationServer.automations.commands.map(c => c.name).join(" ");
console.error(`[ERROR] Unable to find command ${ci.name}, available commands: ${commands}`);
process.exit(4);
}
const invocation: CommandInvocation = {
name: ci.name,
args: ci.args ? ci.args.filter(a =>
handler.parameters.some(p => p.name === a.name)) : undefined,
mappedParameters: ci.args ? ci.args.filter(a =>
handler.mapped_parameters.some(p => p.name === a.name)) : undefined,
secrets: ci.args ? ci.args.filter(a => handler.secrets.some(p => p.name === a.name))
.map(a => {
const s = handler.secrets.find(p => p.name === a.name);
return { uri: s.uri, value: a.value };
}) : undefined,
};

try {
automationServer.validateCommandInvocation(invocation);
} catch (e) {
console.error(`[ERROR] Invalid parameters: ${e.message}`);
process.exit(2);
}
try {
const result = await automationServer.invokeCommand(invocation, ctx);
console.log(`Command succeeded: ${stringify(result, null, 2)}`);
} catch (e) {
console.error(`[ERROR] Command failed: ${stringify(e, null, 2)}`);
process.exit(1);
}
process.exit(0);
}
54 changes: 54 additions & 0 deletions src/bin/git-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#! /usr/bin/env node
/*
* Copyright © 2018 Atomist, Inc.
*
* 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.
*/

import * as fs from "fs-extra";
import * as path from "path";

import {
obtainGitInfo,
} from "../internal/env/gitInfo";
import {
logger,
LoggingConfig,
} from "../internal/util/logger";

LoggingConfig.format = "cli";

/**
* Generate git-info.json for automation client.
*/
async function main(): Promise<never> {
try {
const cwd = process.cwd();
const gitInfoName = "git-info.json";
const gitInfoPath = path.join(cwd, gitInfoName);
const gitInfo = await obtainGitInfo(cwd);
await fs.writeJson(gitInfoPath, gitInfo, { spaces: 2, encoding: "utf8" });
logger.info(`Successfully wrote git information to '${gitInfoPath}'`);
process.exit(0);
} catch (e) {
logger.error(`Failed to generate Git information: ${e.message}`);
process.exit(1);
}
throw new Error("Should never get here, process.exit() called above");
}

main()
.catch((err: Error) => {
logger.error(`Unhandled exception: ${err.message}`);
process.exit(101);
});
117 changes: 117 additions & 0 deletions src/bin/gql-gen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#! /usr/bin/env node
/*
* Copyright © 2018 Atomist, Inc.
*
* 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.
*/

import * as child_process from "child_process";
import * as spawn from "cross-spawn";
import * as fs from "fs-extra";
import * as glob from "glob";
import * as path from "path";
import * as util from "util";

import {
logger,
LoggingConfig,
} from "../internal/util/logger";

LoggingConfig.format = "cli";

/**
* Figure out whether the lib directory is named lib or src. lib is
* preferred, meaning if it exists, it is returned and if neither it
* nor src exists, it is returned.
*
* @param cwd directory to use as base for location of lib dir
* @return Resolved, full path to lib directory
*/
function libDir(cwd: string): string {
const lib = path.resolve(cwd, "lib");
const src = path.resolve(cwd, "src");
if (fs.existsSync(lib)) {
return lib;
} else if (fs.existsSync(src)) {
return src;
} else {
return lib;
}
}

/**
* Generate TypeScript typings for GraphQL schema entities.
*/
async function main(): Promise<void> {
try {
const cwd = process.cwd();
const lib = libDir(cwd);

// check if the project has a custom schema
const customSchemaLocation = path.join(lib, "graphql", "schema.json");
const defaultSchemaLocation = path.join(cwd, "node_modules", "@atomist", "automation-client",
"graph", "schema.cortex.json");
const schema = fs.existsSync(customSchemaLocation) ? customSchemaLocation : defaultSchemaLocation;

const gqlGenCmd = path.join(cwd, "node_modules", ".bin", "gql-gen") +
((process.platform === "win32") ? ".cmd" : "");
const gqlGenOutput = path.join(lib, "typings", "types.ts");
const gqlGenArgs = [
"--file", schema,
"--template", "typescript",
"--no-schema",
"--out", gqlGenOutput,
];

const opts: child_process.SpawnOptions = {
cwd,
env: process.env,
stdio: "inherit",
};

const graphQlGlob = `${lib}/**/*.graphql`;

const graphqlFiles = await util.promisify(glob)(graphQlGlob);
if (graphqlFiles && graphqlFiles.length > 0) {
gqlGenArgs.push(graphQlGlob);
} else {
logger.info("No GraphQL files found in project, generating default types");
}

const cp = spawn(gqlGenCmd, gqlGenArgs, opts);
cp.on("exit", (code, signal) => {
if (code === 0) {
process.exit(code);
} else if (code) {
logger.error(`Generating GraphQL failed with non-zero status: ${code}`);
process.exit(code);
} else {
logger.error(`Generating GraphQL exited due to signal: ${signal}`);
process.exit(128 + 2);
}
});
cp.on("error", err => {
logger.error(`Generating GraphQL types errored: ${err.message}`);
process.exit(2);
});
} catch (e) {
logger.error(`Generating GraphQL types failed: ${e.message}`);
process.exit(1);
}
}

main()
.catch((err: Error) => {
logger.error(`Unhandled exception: ${err.message}`);
process.exit(101);
});
22 changes: 22 additions & 0 deletions src/bin/start.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env node

import "source-map-support/register";
import { automationClient } from "../automationClient";
import { loadConfiguration } from "../configuration";
import { enableDefaultScanning } from "../scan";

try {
loadConfiguration()
.then(configuration => {
enableDefaultScanning(configuration);
return configuration;
})
.then(configuration => automationClient(configuration).run())
.catch(e => {
console.error(e);
process.exit(1);
});
} catch (e) {
console.error(`Uncaught exception: ${e.message}`);
process.exit(10);
}
2 changes: 2 additions & 0 deletions src/start.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { automationClient } from "./automationClient";
import { loadConfiguration } from "./configuration";
import { enableDefaultScanning } from "./scan";

console.warn("[WARN] This script is deprecated, use 'bin/start.js'");

try {
loadConfiguration()
.then(configuration => {
Expand Down
2 changes: 2 additions & 0 deletions src/start.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { AutomationServer } from "./server/AutomationServer";

LoggingConfig.format = "cli";

console.warn("[WARN] This script is deprecated, use 'bin/command.js'");

main();

/**
Expand Down
2 changes: 2 additions & 0 deletions src/start.git-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {

LoggingConfig.format = "cli";

console.warn("[WARN] This script is deprecated, use 'bin/git-info.js'");

/**
* Generate git-info.json for automation client.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/start.gql-gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import {

LoggingConfig.format = "cli";

console.warn("[WARN] This script is deprecated, use 'bin/gql-gen.js'");

/**
* Figure out whether the lib directory is named lib or src. lib is
* preferred, meaning if it exists, it is returned and if neither it
Expand Down

0 comments on commit 3a61594

Please sign in to comment.