From 39e8f2f81d1f12049ae454af796ed4d98e9cc721 Mon Sep 17 00:00:00 2001 From: Nicolas R Date: Fri, 17 Apr 2020 15:41:38 -0600 Subject: [PATCH] Install modules using cpanm --- .github/workflows/check.yml | 150 +++++++++++++++++++++++++++++- README.md | 177 ++++++++++++++++++++++++++++++++++-- action.yml | 38 +++++++- index.js | 144 +++++++++++++++++++++++++++-- 4 files changed, 493 insertions(+), 16 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d9e66b1..a5ec85f 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -3,12 +3,158 @@ name: check on: [push] jobs: - testing: + cpanm: runs-on: ubuntu-latest - name: Testing GitHub action + name: "install cpanm" steps: - uses: actions/checkout@v2 - name: uses install-with-cpanm uses: ./ - name: which cpanm run: which cpanm + + ### ------------------------------------------------ + ### Install a single module + ### ------------------------------------------------ + + one_module: + runs-on: ubuntu-latest + name: "cpanm and a module" + steps: + - uses: actions/checkout@v2 + - name: uses install-with-cpanm + uses: ./ + with: + install: "Simple::Accessor" + - run: perl -MSimple::Accessor -e1 + + ### ------------------------------------------------ + ### Install multiple modules + ### ------------------------------------------------ + + multiple_modules: + runs-on: ubuntu-latest + name: "cpanm & modules" + steps: + - uses: actions/checkout@v2 + - name: uses install-with-cpanm + uses: ./ + with: + install: | + Simple::Accessor + abbreviation + - run: perl -MSimple::Accessor -e1 + - run: perl -Mabbreviation -e1 + + ### ------------------------------------------------ + ### Install modules from a cpanfile + ### ------------------------------------------------ + + cpanfile_root: + runs-on: ubuntu-latest + name: "cpanfile as root" + steps: + - uses: actions/checkout@v2 + - name: "Create a cpanfile" + run: | + echo "requires 'Simple::Accessor';" > cpanfile.test + - name: uses install-with-cpanm + uses: ./ + with: + cpanfile: "cpanfile.test" + - run: perl -MSimple::Accessor -e1 + + cpanfile_nonroot: + runs-on: ubuntu-latest + name: "cpanfile nonroot local::lib" + steps: + - uses: actions/checkout@v2 + - name: "Create a cpanfile" + run: | + echo "requires 'Simple::Accessor';" > cpanfile.test + - name: uses install-with-cpanm + uses: ./ + with: + path: "cpanm-local" + cpanfile: "cpanfile.test" + sudo: false + args: "-L vendor" + - run: sudo perl cpanm-local local::lib + - run: perl -Mlocal::lib=--no-create,vendor -MSimple::Accessor -e1 + + ### ------------------------------------------------ + ### Install a module and enable tests + ### ------------------------------------------------ + + with_tests: + runs-on: ubuntu-latest + name: "install with tests" + steps: + - uses: actions/checkout@v2 + - name: uses install-with-cpanm + uses: ./ + with: + install: "Simple::Accessor" + tests: true + args: "-v" + - run: perl -MSimple::Accessor -e1 + + ### ------------------------------------------------ + ### check perl-tester + ### ------------------------------------------------ + + perl_tester: + runs-on: ubuntu-latest + name: "perl v${{ matrix.perl-version }}" + + strategy: + fail-fast: false + matrix: + perl-version: + - "5.30" + - "5.28" + # ... + + container: + image: perldocker/perl-tester:${{ matrix.perl-version }} + + steps: + - uses: actions/checkout@v2 + - name: uses install-with-cpanm + uses: ./ + with: + sudo: false + install: | + abbreviation + ACH + # checking that both modules are installed + - run: perl -Mabbreviation -e1 + - run: perl -MACH -e1 + + ## ------------------------------------------------ + ## testing with windows + ## ------------------------------------------------ + windows: + runs-on: windows-latest + name: "windows" + + steps: + - name: Set up Perl + run: | + choco install strawberryperl + echo "##[add-path]C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin" + + - name: perl -V + run: perl -V + + - uses: actions/checkout@v2 + - name: "install-with-cpanm" + + uses: ./ + with: + install: | + abbreviation + ACH + # checking that both modules are installed + - run: perl -Mabbreviation -e1 + - run: perl -MACH -e1 diff --git a/README.md b/README.md index 1c4f3ca..40a966b 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,103 @@ # install-with-cpanm -GitHub action to install Perl Modules App::cpanminus +GitHub action to install Perl Modules [App::cpanminus](https://github.com/miyagawa/cpanminus) -This action installs 'cpanminus' as root so you can then use it in your workflow. +This action installs 'cpanminus' then use it if needed to install some Perl Modules. + +```yaml +- name: install cpanm and multiple modules + uses: perl-actions/install-with-cpanm@v1.1 + with: + install: | + Simple::Accessor + Test::Parallel + +# or you can use a cpanfile +# cpanfile: 'your-cpanfile' +# default values you can customize +# sudo: true +# where to install cpanm +# path: "$Config{installsitescript}/cpanm" +# which perl binary to use +# perl: 'perl' +``` + +## Using install-with-cpanm in a GitHub workflow + +Here is a sample integration using install-with-cpanm action +to test your Perl Modules using multiple Perl versions via the +perl-tester images. + +```yaml +# .github/workflows/linux.yml +jobs: + perl_tester: + runs-on: ubuntu-latest + name: "perl v${{ matrix.perl-version }}" + + strategy: + fail-fast: false + matrix: + perl-version: + - "5.30" + - "5.28" + - "5.26" + # ... + # - '5.8' + + container: + image: perldocker/perl-tester:${{ matrix.perl-version }} + + steps: + - uses: actions/checkout@v2 + - name: uses install-with-cpm + uses: perl-actions/install-with-cpanm@v1.1 + with: + cpanfile: "cpanfile" + sudo: false + - run: perl Makefile.PL + - run: make test +``` ## Inputs -none +### `install` + +List of one or more modules, separated by a newline `\n` character. + +### `cpanfile` + +Install modules from a cpanfile. + +### `tests` + +Boolean variable used to disable unit tests during installation +Possible values: true | false [default: false] + +### `args` + +Extra arguments to pass to the cpanm command line. + +example: + +```yaml +args: "-L vendor" +``` + +### `sudo` + +Run commands as sudo: true | false [default: true] + +### `perl` + +Which perl path to use. Default to use `perl` from the current `PATH`. +By setting PATH correctly you probably do not need to use it. + +### `path` + +Where to install `cpanm`. Default value is `$Config{installsitescript}/cpanm`. +You can use any `$Config` variable in your string. ## Outputs @@ -16,8 +106,83 @@ none ## Example usage +### Install cpanm and use it manually later + +```yaml +uses: perl-actions/install-with-cpanm@v1.1 +# you can then use it later +run: sudo cpanm Module::To::Install +``` + +but you should prefer let the action install your modules + +### Install cpanm and a single module + +```yaml +- name: install cpanm and one module + uses: perl-actions/install-with-cpanm@v1.1 + with: + install: "Simple::Accessor" +``` + +### Install cpanm and multiple modules + +```yaml +- name: install cpanm and one module + uses: perl-actions/install-with-cpanm@v1.1 + with: + install: | + Simple::Accessor + Test::Parallel +``` + +### Install modules from a cpanfile + +```yaml +- name: install cpanm and files from cpanfile + uses: perl-actions/install-with-cpanm@v1.1 + with: + cpanfile: "your-cpanfile" +``` + +### Install a module and enable tests + +Install modules with tests. + +```yaml +- name: install cpm and files from cpanfile + uses: perl-actions/install-with-cpanm@v1.1 + with: + install: "Simple::Accessor" + tests: true ``` -uses: perl-actions/install-with-cpanm@v1.0 -run: | - sudo cpanm Module::To::Install + +### Using install-with-cpm on Windows / win32 + +Here is a sample job using cpanm to install modules on windows. + +```yaml +windows: + runs-on: windows-latest + name: "windows" + + steps: + - name: Set up Perl + run: | + choco install strawberryperl + echo "##[add-path]C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin" + + - name: perl -V + run: perl -V + + - uses: actions/checkout@v2 + - name: "install-with-cpanm" + uses: perl-actions/install-with-cpm@v1.1 + with: + install: | + abbreviation + ACH + # checking that both modules are installed + - run: perl -Mabbreviation -e1 + - run: perl -MACH -e1 ``` diff --git a/action.yml b/action.yml index 1754d31..6405b19 100644 --- a/action.yml +++ b/action.yml @@ -1,8 +1,42 @@ -name: "install cpanm" -description: "install App::cpanminus" +name: "install with cpanm" +description: "install Perl Modules with App::cpanminus" branding: icon: "arrow-right" color: "blue" + +inputs: + install: + description: "List of modules or distributions to install [seperated by newline]" + required: false + + cpanfile: + description: "Use a cpanfile to install modules" + required: false + + tests: + description: "Run or not the unit tests" + required: false + default: false + + args: + description: "Extra args used passed to install command" + required: false + + sudo: + description: "Perform installations as root" + required: false + default: true + + perl: + description: "Path of perl to use default to current PATH" + required: false + default: "perl" + + path: + description: "Path where to install cpanm: the string can use $Config values" + required: false + default: "$Config{installsitescript}/cpanm" + runs: using: "node12" main: "index.js" diff --git a/index.js b/index.js index 20de139..43b748b 100644 --- a/index.js +++ b/index.js @@ -2,18 +2,150 @@ const core = require("@actions/core"); const github = require("@actions/github"); const tc = require("@actions/tool-cache"); const exec = require("@actions/exec"); +const io = require("@actions/io"); + +const fs = require("fs"); +const path = require("path"); +const os = require("os"); + +var PERL; + +async function install_cpanm_location() { + let out = ""; + + const options = {}; + options.listeners = { + stdout: (data) => { + out += data.toString(); + }, + }; + + var p = core.getInput("path"); + p.replace("\\", "\\\\"); + await exec.exec(PERL, ["-MConfig", "-e", `print "${p}"`], options); + + return path.resolve(out); +} + +async function install_cpanm(install_to) { + const url = "https://cpanmin.us"; + + core.setOutput(`Get cpanm from ${url}`); + + const cpanmScript = await tc.downloadTool(url); + + core.setOutput("cpanm", cpanmScript); + console.log(`install_to ${install_to}`); + + const platform = os.platform(); + + if (platform == "win32") { + await io.cp(cpanmScript, install_to); + } else { + await do_exec([ + PERL, + "-MFile::Copy=cp", + "-e", + `cp("${cpanmScript}", "${install_to}"); chmod(0755, "${install_to}")`, + ]); + } + //await ioUtil.chmod(install_to, '0755') + + return install_to; +} + +async function which_perl() { + const perl = core.getInput("perl"); + if (perl == "perl") { + return await io.which("perl", true); + } + return perl; +} + +function is_true(b) { + if (b !== null && (b === true || b == "true" || b == "1" || b == "ok")) { + return true; + } + + return false; +} + +function is_false(b) { + return is_true(b) ? false : true; +} + +async function do_exec(cmd) { + const sudo = is_true(core.getInput("sudo")); + const platform = os.platform(); + const bin = sudo && platform != "win32" ? "sudo" : cmd.shift(); + + console.log(`do_exec: ${bin}`); + + await exec.exec(bin, cmd); +} + +async function run() { + PERL = await which_perl(); + + const cpanm_location = await install_cpanm_location(); + + await install_cpanm(cpanm_location); + + // input arguments + const install = core.getInput("install"); + const cpanfile = core.getInput("cpanfile"); + const tests = core.getInput("tests"); + const dash_g = core.getInput("global"); + const args = core.getInput("args"); + + const w_tests = is_true(tests) ? null : "--notest"; + var w_args = []; + + if (args !== null && args.length) { + w_args = args.split(/\s+/); + } + + /* base CMD_install command */ + var CMD_install = [PERL, cpanm_location, "-v"]; + if (w_tests != null) { + CMD_install.push(w_tests); + } + + if (w_args.length) { + CMD_install = CMD_install.concat(w_args); + } + + /* install one ore more modules */ + if (install !== null && install.length) { + // install one or more modules + console.log(`install: ${install}!`); + const list = install.split("\n"); + + var cmd = [...CMD_install]; /* clone array */ + cmd = cmd.concat(list); + + await do_exec(cmd); + } + + /* install from cpanfile */ + if (cpanfile !== null && cpanfile.length) { + // install one or more modules + console.log(`cpanfile: ${cpanfile}!`); + const cpanfile_full_path = path.resolve(cpanfile); + console.log(`cpanfile: ${cpanfile_full_path}! [resolved]`); + + var cmd = [...CMD_install]; + cmd.push("--cpanfile", cpanfile_full_path, "--installdeps", "."); + await do_exec(cmd); + } -async function action() { - const cpanm = await tc.downloadTool("https://cpanmin.us"); - core.setOutput("cpanminus", cpanm); - await exec.exec("sudo", ["perl", cpanm, "App::cpanminus"]); return; } -// Call action +// Call run (async () => { try { - await action(); + await run(); } catch (error) { core.setFailed(error.message); }