diff --git a/dist/action.js b/dist/action.js index df449d1..fe1eb49 100644 --- a/dist/action.js +++ b/dist/action.js @@ -1,38 +1,38 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const core_1 = require("@actions/core"); -const github_1 = require("@actions/github"); -const core_2 = require("./core"); -if (require.main === module) { - console.log("Tangle Release Starting"); - const releaseTag = core_1.getInput("tag_name", { required: true }); - const comment = core_1.getInput("comment", { required: false }); - const { owner, repo } = github_1.context.repo; - const envConfig = { - githubToken: process.env.GITHUB_TOKEN, - owner, - repository: repo, - releaseTag, - node: process.env.IOTA_NODE, - depth: process.env.IOTA_DEPTH, - mwm: process.env.IOTA_MWM, - seed: process.env.IOTA_SEED, - addressIndex: process.env.IOTA_ADDRESS_INDEX, - transactionTag: process.env.IOTA_TAG, - comment, - explorerUrl: process.env.IOTA_TANGLE_EXPLORER - }; - const config = core_2.sanitizeInput(envConfig); - core_2.tangleRelease(config, message => console.log(message)) - .then(transactionDetails => { - core_1.setOutput("tx_hash", transactionDetails.hash); - core_1.setOutput("tx_explore_url", transactionDetails.url); - console.log("Transaction Hash:", transactionDetails.hash); - console.log("You can view the transaction on the tangle at:", transactionDetails.url); - console.log("Complete"); - }) - .catch(err => { - core_1.setFailed(err.message); - console.log(err); - }); -} +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const core_1 = require("@actions/core"); +const github_1 = require("@actions/github"); +const core_2 = require("./core"); +if (require.main === module) { + console.log("Tangle Release Starting"); + const releaseTag = core_1.getInput("tag_name", { required: true }); + const comment = core_1.getInput("comment", { required: false }); + const { owner, repo } = github_1.context.repo; + const envConfig = { + githubToken: process.env.GITHUB_TOKEN, + owner, + repository: repo, + releaseTag, + node: process.env.IOTA_NODE, + depth: process.env.IOTA_DEPTH, + mwm: process.env.IOTA_MWM, + seed: process.env.IOTA_SEED, + addressIndex: process.env.IOTA_ADDRESS_INDEX, + transactionTag: process.env.IOTA_TAG, + comment, + explorerUrl: process.env.IOTA_TANGLE_EXPLORER + }; + const config = core_2.sanitizeInput(envConfig); + core_2.tangleRelease(config, message => console.log(message)) + .then(transactionDetails => { + core_1.setOutput("tx_hash", transactionDetails.hash); + core_1.setOutput("tx_explore_url", transactionDetails.url); + console.log("Transaction Hash:", transactionDetails.hash); + console.log("You can view the transaction on the tangle at:", transactionDetails.url); + console.log("Complete"); + }) + .catch(err => { + core_1.setFailed(err.message); + console.log(err); + }); +} diff --git a/dist/cli-core.js b/dist/cli-core.js index 7507f59..0c65b71 100644 --- a/dist/cli-core.js +++ b/dist/cli-core.js @@ -1,124 +1,124 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.cliCore = void 0; -const chalk_1 = __importDefault(require("chalk")); -const commander_1 = require("commander"); -const node_emoji_1 = __importDefault(require("node-emoji")); -const core_1 = require("./core"); -/** - * Execute the cli core. - * @param argv The command line arguments. - * @param env The environment variables. - * @param display Method to output display. - */ -function cliCore(argv, env, display) { - return __awaiter(this, void 0, void 0, function* () { - const program = new commander_1.Command(); - try { - const version = "0.7.1"; - program - .storeOptionsAsProperties(false) - .passCommandToAction(false) - .name(chalk_1.default.yellowBright("gh-tangle-release")) - .version(version, "-v, --version", chalk_1.default.yellowBright("output the current version")) - .description(chalk_1.default.cyan("An application for creating a transaction on the IOTA Tangle from a GitHub release.")) - .option("--github-token ", chalk_1.default.yellowBright("GitHub token for accessing your repository (required)")) - .option("--owner ", chalk_1.default.yellowBright("GitHub repository owner (required)")) - .option("--repository ", chalk_1.default.yellowBright("GitHub repository (required)")) - .option("--release-tag ", chalk_1.default.yellowBright("The release tag from the GitHub repository (required)")) - .option("--node ", chalk_1.default.yellowBright("Url of the node to use for attaching the transaction to the tangle"), "https://nodes.iota.cafe:443") - .option("--depth ", chalk_1.default.yellowBright("Depth to use for attaching the transaction to the tangle"), "3") - .option("--mwm ", chalk_1.default.yellowBright("Minimum weight magnitude to use for attaching the transaction to the tangle"), "14") - .option("--seed ", chalk_1.default.yellowBright("81 Tryte seed used to generate addresses (required)")) - .option("--address-index ", chalk_1.default.yellowBright("Index number used to generate addresses"), "0") - .option("--transaction-tag ", chalk_1.default.yellowBright("Tag to apply to the Tangle transaction"), "GITHUB9RELEASE") - .option("--comment ", chalk_1.default.yellowBright("An optional comment to include in the Tangle transaction payload")) - .option("--explorer-url ", chalk_1.default.yellowBright("Url of the explorer to use for exploration link"), "https://utils.iota.org/transaction/:hash") - .option("--no-color", chalk_1.default.yellowBright("Disable colored output")) - .helpOption("--help", chalk_1.default.yellowBright("Display help")); - program.parse(argv); - const opts = program.opts(); - console.log(opts); - display(chalk_1.default.green(`GitHub Tangle Release v${version} ${opts.color === false ? "" : node_emoji_1.default.get("rocket")}\n`)); - const envRepo = env.GITHUB_REPOSITORY ? env.GITHUB_REPOSITORY.split("/") : []; - if (envRepo.length === 2) { - opts.owner = opts.owner || envRepo[0]; - opts.repository = opts.repository || envRepo[1]; - } - const config = core_1.sanitizeInput({ - githubToken: opts.githubToken || env.GITHUB_TOKEN, - owner: opts.owner, - repository: opts.repository, - releaseTag: opts.releaseTag || env.GITHUB_REF, - node: opts.node, - depth: opts.depth, - mwm: opts.mwm, - seed: opts.seed || env.GTR_SEED, - addressIndex: opts.addressIndex, - transactionTag: opts.transactionTag, - comment: opts.comment, - explorerUrl: opts.explorerUrl - }); - display("Options:"); - display(chalk_1.default.cyan("\tGitHub Token"), chalk_1.default.white("*******")); - display(chalk_1.default.cyan("\tOwner"), chalk_1.default.white(config.owner)); - display(chalk_1.default.cyan("\tRepository"), chalk_1.default.white(config.repository)); - display(chalk_1.default.cyan("\tRelease Tag"), chalk_1.default.white(config.releaseTag)); - display(chalk_1.default.cyan("\tNode"), chalk_1.default.white(config.node)); - display(chalk_1.default.cyan("\tDepth"), chalk_1.default.white(config.depth)); - display(chalk_1.default.cyan("\tMWM"), chalk_1.default.white(config.mwm)); - display(chalk_1.default.cyan("\tSeed"), chalk_1.default.white("*******")); - display(chalk_1.default.cyan("\tAddress Index"), chalk_1.default.white(config.addressIndex)); - display(chalk_1.default.cyan("\tTransaction Tag"), chalk_1.default.white(config.transactionTag)); - if (config.comment) { - display(chalk_1.default.cyan("\tComment"), chalk_1.default.white(config.comment)); - } - display(chalk_1.default.cyan("\tExplorer Url"), chalk_1.default.white(config.explorerUrl)); - display(""); - try { - const transactionDetails = yield core_1.tangleRelease(config, message => display(chalk_1.default.green(message))); - display("Transaction Hash:", chalk_1.default.cyan(transactionDetails.hash)); - display("You can view the transaction on the tangle at:", chalk_1.default.cyan(transactionDetails.url)); - display(chalk_1.default.green("Complete")); - } - catch (err) { - display(""); - display(createErrors(err)); - process.exit(1); - } - } - catch (err) { - program.help(str => `${str}${createEnvHelp()}${createExample()}${createErrors(err)}`); - process.exit(1); - } - }); -} -exports.cliCore = cliCore; -/** - * Show an example on the console. - * @returns The example text. - */ -function createExample() { - // eslint-disable-next-line max-len - return chalk_1.default.magenta("\nExample: gh-tangle-release --github-token a4d936470cb3d66f5434f787c2500bde9764f --owner my-org --repository my-repo --release-tag v1.0.1 --seed AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\n"); -} -/** - * Show additional info about env vars. - * @returns The additional information. - */ -function createEnvHelp() { +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.cliCore = void 0; +const chalk_1 = __importDefault(require("chalk")); +const commander_1 = require("commander"); +const node_emoji_1 = __importDefault(require("node-emoji")); +const core_1 = require("./core"); +/** + * Execute the cli core. + * @param argv The command line arguments. + * @param env The environment variables. + * @param display Method to output display. + */ +function cliCore(argv, env, display) { + return __awaiter(this, void 0, void 0, function* () { + const program = new commander_1.Command(); + try { + const version = "0.7.1"; + program + .storeOptionsAsProperties(false) + .passCommandToAction(false) + .name(chalk_1.default.yellowBright("gh-tangle-release")) + .version(version, "-v, --version", chalk_1.default.yellowBright("output the current version")) + .description(chalk_1.default.cyan("An application for creating a transaction on the IOTA Tangle from a GitHub release.")) + .option("--github-token ", chalk_1.default.yellowBright("GitHub token for accessing your repository (required)")) + .option("--owner ", chalk_1.default.yellowBright("GitHub repository owner (required)")) + .option("--repository ", chalk_1.default.yellowBright("GitHub repository (required)")) + .option("--release-tag ", chalk_1.default.yellowBright("The release tag from the GitHub repository (required)")) + .option("--node ", chalk_1.default.yellowBright("Url of the node to use for attaching the transaction to the tangle"), "https://nodes.iota.cafe:443") + .option("--depth ", chalk_1.default.yellowBright("Depth to use for attaching the transaction to the tangle"), "3") + .option("--mwm ", chalk_1.default.yellowBright("Minimum weight magnitude to use for attaching the transaction to the tangle"), "14") + .option("--seed ", chalk_1.default.yellowBright("81 Tryte seed used to generate addresses (required)")) + .option("--address-index ", chalk_1.default.yellowBright("Index number used to generate addresses"), "0") + .option("--transaction-tag ", chalk_1.default.yellowBright("Tag to apply to the Tangle transaction"), "GITHUB9RELEASE") + .option("--comment ", chalk_1.default.yellowBright("An optional comment to include in the Tangle transaction payload")) + .option("--explorer-url ", chalk_1.default.yellowBright("Url of the explorer to use for exploration link"), "https://utils.iota.org/transaction/:hash") + .option("--no-color", chalk_1.default.yellowBright("Disable colored output")) + .helpOption("--help", chalk_1.default.yellowBright("Display help")); + program.parse(argv); + const opts = program.opts(); + console.log(opts); + display(chalk_1.default.green(`GitHub Tangle Release v${version} ${opts.color === false ? "" : node_emoji_1.default.get("rocket")}\n`)); + const envRepo = env.GITHUB_REPOSITORY ? env.GITHUB_REPOSITORY.split("/") : []; + if (envRepo.length === 2) { + opts.owner = opts.owner || envRepo[0]; + opts.repository = opts.repository || envRepo[1]; + } + const config = core_1.sanitizeInput({ + githubToken: opts.githubToken || env.GITHUB_TOKEN, + owner: opts.owner, + repository: opts.repository, + releaseTag: opts.releaseTag || env.GITHUB_REF, + node: opts.node, + depth: opts.depth, + mwm: opts.mwm, + seed: opts.seed || env.GTR_SEED, + addressIndex: opts.addressIndex, + transactionTag: opts.transactionTag, + comment: opts.comment, + explorerUrl: opts.explorerUrl + }); + display("Options:"); + display(chalk_1.default.cyan("\tGitHub Token"), chalk_1.default.white("*******")); + display(chalk_1.default.cyan("\tOwner"), chalk_1.default.white(config.owner)); + display(chalk_1.default.cyan("\tRepository"), chalk_1.default.white(config.repository)); + display(chalk_1.default.cyan("\tRelease Tag"), chalk_1.default.white(config.releaseTag)); + display(chalk_1.default.cyan("\tNode"), chalk_1.default.white(config.node)); + display(chalk_1.default.cyan("\tDepth"), chalk_1.default.white(config.depth)); + display(chalk_1.default.cyan("\tMWM"), chalk_1.default.white(config.mwm)); + display(chalk_1.default.cyan("\tSeed"), chalk_1.default.white("*******")); + display(chalk_1.default.cyan("\tAddress Index"), chalk_1.default.white(config.addressIndex)); + display(chalk_1.default.cyan("\tTransaction Tag"), chalk_1.default.white(config.transactionTag)); + if (config.comment) { + display(chalk_1.default.cyan("\tComment"), chalk_1.default.white(config.comment)); + } + display(chalk_1.default.cyan("\tExplorer Url"), chalk_1.default.white(config.explorerUrl)); + display(""); + try { + const transactionDetails = yield core_1.tangleRelease(config, message => display(chalk_1.default.green(message))); + display("Transaction Hash:", chalk_1.default.cyan(transactionDetails.hash)); + display("You can view the transaction on the tangle at:", chalk_1.default.cyan(transactionDetails.url)); + display(chalk_1.default.green("Complete")); + } + catch (err) { + display(""); + display(createErrors(err)); + process.exit(1); + } + } + catch (err) { + program.help(str => `${str}${createEnvHelp()}${createExample()}${createErrors(err)}`); + process.exit(1); + } + }); +} +exports.cliCore = cliCore; +/** + * Show an example on the console. + * @returns The example text. + */ +function createExample() { + // eslint-disable-next-line max-len + return chalk_1.default.magenta("\nExample: gh-tangle-release --github-token a4d936470cb3d66f5434f787c2500bde9764f --owner my-org --repository my-repo --release-tag v1.0.1 --seed AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n\n"); +} +/** + * Show additional info about env vars. + * @returns The additional information. + */ +function createEnvHelp() { return ` ${chalk_1.default.cyan("You can also supply some of the options through environment variables:")} ${chalk_1.default.cyan("--github-token: GITHUB_TOKEN")} @@ -126,13 +126,13 @@ ${chalk_1.default.cyan("You can also supply some of the options through environm ${chalk_1.default.cyan("--repository: GITHUB_REPOSITORY[1]")} ${chalk_1.default.cyan(" where GITHUB_REPOSITORY is formatted owner/repository")} ${chalk_1.default.cyan("--release-tag: GITHUB_REF")} - ${chalk_1.default.cyan("--seed: GTR_SEED")}\n\n`; -} -/** - * Show the errors. - * @param error The error that was thrown. - * @returns The formatted errors. - */ -function createErrors(error) { - return chalk_1.default.red(`The following errors occurred:\n ${error.message.replace(/\n/g, "\n ")}`); -} + ${chalk_1.default.cyan("--seed: GTR_SEED")}\n\n`; +} +/** + * Show the errors. + * @param error The error that was thrown. + * @returns The formatted errors. + */ +function createErrors(error) { + return chalk_1.default.red(`The following errors occurred:\n ${error.message.replace(/\n/g, "\n ")}`); +} diff --git a/dist/cli.js b/dist/cli.js index 472e37b..af0bb0f 100644 --- a/dist/cli.js +++ b/dist/cli.js @@ -1,11 +1,11 @@ -#!/usr/bin/env node -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const cli_core_1 = require("./cli-core"); -cli_core_1.cliCore(process.argv, process.env, (message, param) => { - process.stdout.write(message); - if (param) { - process.stdout.write(` ${param}`); - } - process.stdout.write("\n"); -}).catch(err => process.stderr.write(err.message)); +#!/usr/bin/env node +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const cli_core_1 = require("./cli-core"); +cli_core_1.cliCore(process.argv, process.env, (message, param) => { + process.stdout.write(message); + if (param) { + process.stdout.write(` ${param}`); + } + process.stdout.write("\n"); +}).catch(err => process.stderr.write(err.message)); diff --git a/dist/core.js b/dist/core.js index 8420601..1d08179 100644 --- a/dist/core.js +++ b/dist/core.js @@ -1,171 +1,171 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.tangleRelease = exports.sanitizeInput = void 0; -/* eslint-disable camelcase */ -const github_1 = require("@actions/github"); -const crypto_1 = require("./crypto"); -const iota_1 = require("./iota"); -/** - * Santirize the input parameters. - * @param config The config for the release. - * @returns The config as non partial. - */ -function sanitizeInput(config) { - const errors = []; - if (!config.githubToken) { - errors.push("You must provide the GitHub token option"); - } - if (!config.owner) { - errors.push("You must provide the owner option"); - } - if (!config.repository) { - errors.push("You must provide the repository option"); - } - if (!config.releaseTag) { - errors.push("You must provide the release tag option"); - } - if (!config.seed) { - errors.push("You must provide the seed option"); - } - else if (!/[9A-Z]/.test(config.seed)) { - errors.push("The seed option must be 81 trytes [A-Z9]"); - } - else if (config.seed.length !== 81) { - errors.push(`The seed option must be 81 trytes [A-Z9], it is ${config.seed.length}`); - } - config.transactionTag = config.transactionTag || "GITHUB9RELEASE"; - if (!/[9A-Z]/.test(config.transactionTag)) { - errors.push("The transaction tag option must be 27 trytes [A-Z9] or less"); - } - if (config.transactionTag.length > 27) { - errors.push(`The transaction tag option must be 27 trytes [A-Z9] or less, it is ${config.transactionTag.length}`); - } - config.explorerUrl = config.explorerUrl || "https://utils.iota.org/transaction/:hash"; - config.node = config.node || "https://nodes.iota.cafe:443"; - let addressIndex; - let depth; - let mwm; - if (typeof config.addressIndex === "string") { - addressIndex = config.addressIndex.length > 0 ? Number.parseInt(config.addressIndex, 10) : 0; - } - else if (config.addressIndex === undefined || config.addressIndex === null) { - addressIndex = 0; - } - else { - addressIndex = config.addressIndex; - } - if (typeof config.depth === "string") { - depth = config.depth.length > 0 ? Number.parseInt(config.depth, 10) : 3; - } - else if (config.depth === undefined || config.depth === null) { - depth = 3; - } - else { - depth = config.depth; - } - if (typeof config.mwm === "string") { - mwm = config.mwm.length > 0 ? Number.parseInt(config.mwm, 10) : 14; - } - else if (config.mwm === undefined || config.mwm === null) { - mwm = 14; - } - else { - mwm = config.mwm; - } - if (errors.length > 0) { - throw new Error(errors.join("\n")); - } - return { - githubToken: config.githubToken || "", - owner: config.owner || "", - repository: config.repository || "", - releaseTag: config.releaseTag || "", - node: config.node, - depth, - mwm, - seed: config.seed || "", - addressIndex, - transactionTag: config.transactionTag, - comment: config.comment, - explorerUrl: config.explorerUrl - }; -} -exports.sanitizeInput = sanitizeInput; -/** - * Create a tangle payload for a GitHub release. - * @param config The config for the release. - * @param progress Callback to send progress to. - * @returns The hash of the transaction and an explorer url. - */ -function tangleRelease(config, progress) { - return __awaiter(this, void 0, void 0, function* () { - progress("Connecting to GitHub"); - let release; - try { - const octokit = github_1.getOctokit(config.githubToken); - release = yield octokit.repos.getReleaseByTag({ - owner: config.owner, - repo: config.repository, - tag: config.releaseTag.replace("refs/tags/", "") - }); - if (!release) { - throw new Error("Unable to retrieve release"); - } - } - catch (err) { - if (!err.toString().includes("Not Found")) { - throw err; - } - } - if (!release) { - throw new Error(`Can not find the release https://github.com/${config.owner}/${config.repository}/releases/tag/${config.releaseTag}`); - } - progress("Downloading tarball"); - const tarBallHash = yield crypto_1.downloadAndHash(release.data.tarball_url, config.githubToken); - progress("Downloading zipball"); - const zipBallHash = yield crypto_1.downloadAndHash(release.data.zipball_url, config.githubToken); - progress("Constructing payload"); - const payload = { - owner: config.owner || "", - repo: config.repository || "", - tag_name: release.data.tag_name, - name: release.data.name, - comment: config.comment, - body: release.data.body, - tarball_url: release.data.tarball_url, - tarball_sig: tarBallHash, - zipball_url: release.data.zipball_url, - zipball_sig: zipBallHash, - assets: undefined - }; - progress("Processing assets"); - if (release.data.assets && release.data.assets.length > 0) { - payload.assets = []; - for (let i = 0; i < release.data.assets.length; i++) { - const assetHash = yield crypto_1.downloadAndHash(release.data.assets[i].browser_download_url, config.githubToken); - payload.assets.push({ - name: release.data.assets[i].name, - size: release.data.assets[i].size, - url: release.data.assets[i].browser_download_url, - sig: assetHash - }); - } - } - progress("Attaching to tangle"); - const txHash = yield iota_1.attachToTangle(config.node, config.depth, config.mwm, config.seed, config.addressIndex, config.transactionTag, payload, progress); - return { - hash: txHash, - url: config.explorerUrl.replace(":hash", txHash) - }; - }); -} -exports.tangleRelease = tangleRelease; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.tangleRelease = exports.sanitizeInput = void 0; +/* eslint-disable camelcase */ +const github_1 = require("@actions/github"); +const crypto_1 = require("./crypto"); +const iota_1 = require("./iota"); +/** + * Santirize the input parameters. + * @param config The config for the release. + * @returns The config as non partial. + */ +function sanitizeInput(config) { + const errors = []; + if (!config.githubToken) { + errors.push("You must provide the GitHub token option"); + } + if (!config.owner) { + errors.push("You must provide the owner option"); + } + if (!config.repository) { + errors.push("You must provide the repository option"); + } + if (!config.releaseTag) { + errors.push("You must provide the release tag option"); + } + if (!config.seed) { + errors.push("You must provide the seed option"); + } + else if (!/[9A-Z]/.test(config.seed)) { + errors.push("The seed option must be 81 trytes [A-Z9]"); + } + else if (config.seed.length !== 81) { + errors.push(`The seed option must be 81 trytes [A-Z9], it is ${config.seed.length}`); + } + config.transactionTag = config.transactionTag || "GITHUB9RELEASE"; + if (!/[9A-Z]/.test(config.transactionTag)) { + errors.push("The transaction tag option must be 27 trytes [A-Z9] or less"); + } + if (config.transactionTag.length > 27) { + errors.push(`The transaction tag option must be 27 trytes [A-Z9] or less, it is ${config.transactionTag.length}`); + } + config.explorerUrl = config.explorerUrl || "https://utils.iota.org/transaction/:hash"; + config.node = config.node || "https://nodes.iota.cafe:443"; + let addressIndex; + let depth; + let mwm; + if (typeof config.addressIndex === "string") { + addressIndex = config.addressIndex.length > 0 ? Number.parseInt(config.addressIndex, 10) : 0; + } + else if (config.addressIndex === undefined || config.addressIndex === null) { + addressIndex = 0; + } + else { + addressIndex = config.addressIndex; + } + if (typeof config.depth === "string") { + depth = config.depth.length > 0 ? Number.parseInt(config.depth, 10) : 3; + } + else if (config.depth === undefined || config.depth === null) { + depth = 3; + } + else { + depth = config.depth; + } + if (typeof config.mwm === "string") { + mwm = config.mwm.length > 0 ? Number.parseInt(config.mwm, 10) : 14; + } + else if (config.mwm === undefined || config.mwm === null) { + mwm = 14; + } + else { + mwm = config.mwm; + } + if (errors.length > 0) { + throw new Error(errors.join("\n")); + } + return { + githubToken: config.githubToken || "", + owner: config.owner || "", + repository: config.repository || "", + releaseTag: config.releaseTag || "", + node: config.node, + depth, + mwm, + seed: config.seed || "", + addressIndex, + transactionTag: config.transactionTag, + comment: config.comment, + explorerUrl: config.explorerUrl + }; +} +exports.sanitizeInput = sanitizeInput; +/** + * Create a tangle payload for a GitHub release. + * @param config The config for the release. + * @param progress Callback to send progress to. + * @returns The hash of the transaction and an explorer url. + */ +function tangleRelease(config, progress) { + return __awaiter(this, void 0, void 0, function* () { + progress("Connecting to GitHub"); + let release; + try { + const octokit = github_1.getOctokit(config.githubToken); + release = yield octokit.repos.getReleaseByTag({ + owner: config.owner, + repo: config.repository, + tag: config.releaseTag.replace("refs/tags/", "") + }); + if (!release) { + throw new Error("Unable to retrieve release"); + } + } + catch (err) { + if (!err.toString().includes("Not Found")) { + throw err; + } + } + if (!release) { + throw new Error(`Can not find the release https://github.com/${config.owner}/${config.repository}/releases/tag/${config.releaseTag}`); + } + progress("Downloading tarball"); + const tarBallHash = yield crypto_1.downloadAndHash(release.data.tarball_url, config.githubToken); + progress("Downloading zipball"); + const zipBallHash = yield crypto_1.downloadAndHash(release.data.zipball_url, config.githubToken); + progress("Constructing payload"); + const payload = { + owner: config.owner || "", + repo: config.repository || "", + tag_name: release.data.tag_name, + name: release.data.name, + comment: config.comment, + body: release.data.body, + tarball_url: release.data.tarball_url, + tarball_sig: tarBallHash, + zipball_url: release.data.zipball_url, + zipball_sig: zipBallHash, + assets: undefined + }; + progress("Processing assets"); + if (release.data.assets && release.data.assets.length > 0) { + payload.assets = []; + for (let i = 0; i < release.data.assets.length; i++) { + const assetHash = yield crypto_1.downloadAndHash(release.data.assets[i].browser_download_url, config.githubToken); + payload.assets.push({ + name: release.data.assets[i].name, + size: release.data.assets[i].size, + url: release.data.assets[i].browser_download_url, + sig: assetHash + }); + } + } + progress("Attaching to tangle"); + const txHash = yield iota_1.attachToTangle(config.node, config.depth, config.mwm, config.seed, config.addressIndex, config.transactionTag, payload, progress); + return { + hash: txHash, + url: config.explorerUrl.replace(":hash", txHash) + }; + }); +} +exports.tangleRelease = tangleRelease; diff --git a/dist/crypto.js b/dist/crypto.js index 7e9538e..3e64acb 100644 --- a/dist/crypto.js +++ b/dist/crypto.js @@ -1,45 +1,45 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.downloadAndHash = void 0; -const axios_1 = __importDefault(require("axios")); -const crypto_1 = require("crypto"); -/** - * Download a file and return the sha256 hash of it. - * @param url The url of the file to download. - * @param githubToken The access token. - * @returns The sha256 hash of the file. - */ -function downloadAndHash(url, githubToken) { - return __awaiter(this, void 0, void 0, function* () { - try { - const response = yield axios_1.default.get(url, { - headers: { - Authorization: `token ${githubToken}` - }, - responseType: "arraybuffer" - }); - if (response.data) { - const hash = crypto_1.createHash("sha256"); - hash.update(Buffer.from(response.data, "binary")); - return hash.digest("base64"); - } - throw new Error(`No data in asset ${url}`); - } - catch (err) { - throw new Error(`Failed retrieving asset ${url}\n${err.msg}`); - } - }); -} -exports.downloadAndHash = downloadAndHash; +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.downloadAndHash = void 0; +const axios_1 = __importDefault(require("axios")); +const crypto_1 = require("crypto"); +/** + * Download a file and return the sha256 hash of it. + * @param url The url of the file to download. + * @param githubToken The access token. + * @returns The sha256 hash of the file. + */ +function downloadAndHash(url, githubToken) { + return __awaiter(this, void 0, void 0, function* () { + try { + const response = yield axios_1.default.get(url, { + headers: { + Authorization: `token ${githubToken}` + }, + responseType: "arraybuffer" + }); + if (response.data) { + const hash = crypto_1.createHash("sha256"); + hash.update(Buffer.from(response.data, "binary")); + return hash.digest("base64"); + } + throw new Error(`No data in asset ${url}`); + } + catch (err) { + throw new Error(`Failed retrieving asset ${url}\n${err.msg}`); + } + }); +} +exports.downloadAndHash = downloadAndHash; diff --git a/dist/index.js b/dist/index.js index 6cb8c12..6b7af4b 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,13 +1,13 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __exportStar = (this && this.__exportStar) || function(m, exports) { - for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -__exportStar(require("./core"), exports); +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("./core"), exports); diff --git a/dist/iota.js b/dist/iota.js index e1e5775..681cd32 100644 --- a/dist/iota.js +++ b/dist/iota.js @@ -1,68 +1,68 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.attachToTangle = void 0; -const converter_1 = require("@iota/converter"); -const core_1 = require("@iota/core"); -/** - * Attach a payload to the tangle. - * @param provider The node to use for attaching. - * @param depth The depth for the attach. - * @param mwm The minimum weight magniture for the attach. - * @param seed The seed to generate the address. - * @param addressIndex The address index to generate. - * @param tag The tag for the payload. - * @param payload The payload contents. - * @param progress Callback to send progress to. - * @returns The transaction hash that was attached. - */ -function attachToTangle(provider, depth, mwm, seed, addressIndex, tag, payload, progress) { - return __awaiter(this, void 0, void 0, function* () { - const json = JSON.stringify(payload); - const ascii = encodeNonASCII(json); - const messageTrytes = converter_1.asciiToTrytes(ascii); - progress("Preparing transactions"); - progress(`\tMessage Trytes Length: ${messageTrytes.length}`); - progress(`\tNumber of Transactions: ${Math.ceil(messageTrytes.length / 2187)}`); - try { - const iota = core_1.composeAPI({ - provider - }); - const address = core_1.generateAddress(seed, addressIndex); - const trytes = yield iota.prepareTransfers("9".repeat(81), [ - { - address, - value: 0, - message: messageTrytes, - tag - } - ]); - progress("Sending trytes"); - const bundles = yield iota.sendTrytes(trytes, depth, mwm); - return bundles[0].hash; - } - catch (err) { - const msg = err instanceof Error ? err.message : err; - throw new Error(`Sending trytes failed.\n${msg.replace("Error: ", "")}`); - } - }); -} -exports.attachToTangle = attachToTangle; -/** - * Replace non ascii characters with their equivalent. - * @param value The value to convert. - * @returns The converted value. - */ -function encodeNonASCII(value) { - return value - ? value.replace(/[\u007F-\uFFFF]/g, chr => `\\u${`0000${chr.charCodeAt(0).toString(16)}`.slice(-4)}`) - : ""; -} +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.attachToTangle = void 0; +const converter_1 = require("@iota/converter"); +const core_1 = require("@iota/core"); +/** + * Attach a payload to the tangle. + * @param provider The node to use for attaching. + * @param depth The depth for the attach. + * @param mwm The minimum weight magniture for the attach. + * @param seed The seed to generate the address. + * @param addressIndex The address index to generate. + * @param tag The tag for the payload. + * @param payload The payload contents. + * @param progress Callback to send progress to. + * @returns The transaction hash that was attached. + */ +function attachToTangle(provider, depth, mwm, seed, addressIndex, tag, payload, progress) { + return __awaiter(this, void 0, void 0, function* () { + const json = JSON.stringify(payload); + const ascii = encodeNonASCII(json); + const messageTrytes = converter_1.asciiToTrytes(ascii); + progress("Preparing transactions"); + progress(`\tMessage Trytes Length: ${messageTrytes.length}`); + progress(`\tNumber of Transactions: ${Math.ceil(messageTrytes.length / 2187)}`); + try { + const iota = core_1.composeAPI({ + provider + }); + const address = core_1.generateAddress(seed, addressIndex); + const trytes = yield iota.prepareTransfers("9".repeat(81), [ + { + address, + value: 0, + message: messageTrytes, + tag + } + ]); + progress("Sending trytes"); + const bundles = yield iota.sendTrytes(trytes, depth, mwm); + return bundles[0].hash; + } + catch (err) { + const msg = err instanceof Error ? err.message : err; + throw new Error(`Sending trytes failed.\n${msg.replace("Error: ", "")}`); + } + }); +} +exports.attachToTangle = attachToTangle; +/** + * Replace non ascii characters with their equivalent. + * @param value The value to convert. + * @returns The converted value. + */ +function encodeNonASCII(value) { + return value + ? value.replace(/[\u007F-\uFFFF]/g, chr => `\\u${`0000${chr.charCodeAt(0).toString(16)}`.slice(-4)}`) + : ""; +} diff --git a/dist/models/IConfig.js b/dist/models/IConfig.js index ce03781..c8ad2e5 100644 --- a/dist/models/IConfig.js +++ b/dist/models/IConfig.js @@ -1,2 +1,2 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/models/IPartialConfig.js b/dist/models/IPartialConfig.js index ce03781..c8ad2e5 100644 --- a/dist/models/IPartialConfig.js +++ b/dist/models/IPartialConfig.js @@ -1,2 +1,2 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/models/IPayload.js b/dist/models/IPayload.js index ce03781..c8ad2e5 100644 --- a/dist/models/IPayload.js +++ b/dist/models/IPayload.js @@ -1,2 +1,2 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/package-lock.json b/package-lock.json index 56a293d..87e31cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2116,11 +2116,11 @@ } }, "cross-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.5.tgz", - "integrity": "sha512-FFLcLtraisj5eteosnX1gf01qYDCOc4fDy0+euOt8Kn9YBY2NtXL/pCoYPavw24NIQkQqm5ZOLsGD5Zzj0gyew==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz", + "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==", "requires": { - "node-fetch": "2.6.0" + "node-fetch": "2.6.1" } }, "cross-spawn": { @@ -5199,9 +5199,9 @@ } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, "lodash.get": { @@ -5436,9 +5436,9 @@ } }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-int64": { "version": "0.4.0",