diff --git a/.eslintrc b/.eslintrc.json similarity index 82% rename from .eslintrc rename to .eslintrc.json index 49b3d4f..46f1010 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -3,7 +3,7 @@ "es6": true, "node": true }, - "extends": "eslint:recommended", + "extends": "@adobe/eslint-config-aio-lib-config", "globals": { "Atomics": "readonly", "SharedArrayBuffer": "readonly" @@ -14,4 +14,4 @@ }, "rules": { } -} \ No newline at end of file +} diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 0000000..66fc28d --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,14 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + uses: adobe/aio-reusable-workflows/.github/workflows/node.js.yml@main diff --git a/.gitignore b/.gitignore index 25c8fdb..1a1345e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules -package-lock.json \ No newline at end of file +package-lock.json +coverage \ No newline at end of file diff --git a/README.md b/README.md index 389e2c0..279bd33 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [AIO CLI](https://github.com/adobe/aio-cli) support for GitHub actions. This action supports installing AIO CLI to various environments. # Getting Started -You can include the action in your workflow as adobe/aio-cli-setup-action@1.1.0 Example : +You can include the action in your workflow as adobe/aio-cli-setup-action@1.3.0 Example : ``` @@ -15,12 +15,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup CLI - uses: adobe/aio-cli-setup-action@1 + uses: adobe/aio-cli-setup-action@1.3.0 with: os: ubuntu-latest - version: 7.0.0 + version: 10.0.0 ``` Once they are set up you can use adobe/aio-apps-action github action to perform app build, test and deployment. Alternatively, you can directly execute AIO CLI commands in the run block of your workflow files. diff --git a/index.js b/index.js index 05be771..20076b8 100644 --- a/index.js +++ b/index.js @@ -12,31 +12,33 @@ governing permissions and limitations under the License. const core = require('@actions/core') const exec = require('@actions/exec') -try { - const os = core.getInput('os') - const version = core.getInput('version') - console.log(" OS - " + os) - runCommand(os, version) - .then(() => { - console.log("action completed") - }) - .catch(e => { - core.setFailed(e.message); - }) - -} catch (error) { - core.setFailed(error.message); +const main = async () => { + try { + const os = core.getInput('os') + const version = core.getInput('version') + console.log(' OS - ' + os) + await runCommand(os, version) + console.log('action completed') + } catch (error) { + core.setFailed(error.message) + } } -async function runCommand(os, version) { +/** + * Install aio-cli + * @param {string} os OS name + * @param {string} version Version of aio-cli + */ +async function runCommand (os, version) { let commandStr = 'npm install -g @adobe/aio-cli' - if(version) { - console.log(" Version - " + version) + if (version) { + console.log(' Version - ' + version) commandStr = commandStr + '@' + version } - if(os && os.startsWith("ubuntu")) - commandStr = 'sudo ' + commandStr + if (os && os.startsWith('ubuntu')) { commandStr = 'sudo ' + commandStr } await exec.exec(commandStr) await exec.exec('aio --version') } + +module.exports = main() // Run the action diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..fd7a526 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,30 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you 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 REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +module.exports = { + collectCoverage: true, + collectCoverageFrom: [ + './index.js' + ], + coverageThreshold: { + global: { + branches: 100, + lines: 100, + statements: 100, + functions: 100 + } + }, + testEnvironment: 'node', + setupFilesAfterEnv: [ + './test/jest.setup.js' + ], + clearMocks: true +} diff --git a/package.json b/package.json index 529b282..7fd55b0 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "version": "1.3.0", "description": "GitHub Action to setup AIO CLI", "scripts": { + "lint:fix": "npm run lint -- --fix", "lint": "eslint index.js", - "package": "ncc build index.js -o dist/" + "package": "ncc build index.js -o dist/", + "unit-tests": "jest -c jest.config.js", + "test": "npm run unit-tests && npm run lint" }, "dependencies": { "@actions/core": "^1.2.6", @@ -12,7 +15,17 @@ }, "repository": "adobe/aio-cli-setup-action", "devDependencies": { + "@adobe/eslint-config-aio-lib-config": "^3.0.0", "@vercel/ncc": "^0.38.0", - "eslint": "^8.41.0" + "eslint": "^8.56.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jsdoc": "^42.0.0", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^6.1.1", + "jest": "^29.7.0", + "stdout-stderr": "^0.1.13" } } diff --git a/test/index.test.js b/test/index.test.js new file mode 100644 index 0000000..f26cf30 --- /dev/null +++ b/test/index.test.js @@ -0,0 +1,94 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you 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 REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +const core = require('@actions/core') +const exec = require('@actions/exec') + +jest.mock('@actions/core', () => ({ + getInput: jest.fn(), + setFailed: jest.fn() +})) + +jest.mock('@actions/exec', () => ({ + exec: jest.fn() +})) + +beforeEach(() => { + core.getInput.mockClear() +}) + +describe('Install aio cli', () => { + test('Success - aio cli install at latest', async () => { + const os = 'macos-latest' + const version = '' + core.getInput.mockReturnValueOnce(os) + core.getInput.mockReturnValueOnce(version) + await jest.isolateModulesAsync(async () => { + await require('../index') // run the action + }) + expect(exec.exec).toHaveBeenCalledTimes(2) + expect(exec.exec).toHaveBeenCalledWith('npm install -g @adobe/aio-cli') + expect(exec.exec).toHaveBeenCalledWith('aio --version') + }) + + test('Success - aio cli install at specific version', async () => { + const os = 'macos-latest' + const version = '9.0.0' + core.getInput.mockReturnValueOnce(os) + core.getInput.mockReturnValueOnce(version) + await jest.isolateModulesAsync(async () => { + await require('../index') // run the action + }) + expect(exec.exec).toHaveBeenCalledTimes(2) + expect(exec.exec).toHaveBeenCalledWith('npm install -g @adobe/aio-cli@9.0.0') + expect(exec.exec).toHaveBeenCalledWith('aio --version') + }) + + test('Success - aio cli install at latest on ubuntu', async () => { + const os = 'ubuntu-latest' + const version = '' + core.getInput.mockReturnValueOnce(os) + core.getInput.mockReturnValueOnce(version) + await jest.isolateModulesAsync(async () => { + await require('../index') // run the action + }) + expect(exec.exec).toHaveBeenCalledTimes(2) + expect(exec.exec).toHaveBeenCalledWith('sudo npm install -g @adobe/aio-cli') + expect(exec.exec).toHaveBeenCalledWith('aio --version') + }) + + test('Success - aio cli install at specific version on ubuntu', async () => { + const os = 'ubuntu-latest' + const version = '9.0.0' + core.getInput.mockReturnValueOnce(os) + core.getInput.mockReturnValueOnce(version) + await jest.isolateModulesAsync(async () => { + await require('../index') // run the action + }) + expect(exec.exec).toHaveBeenCalledTimes(2) + expect(exec.exec).toHaveBeenCalledWith('sudo npm install -g @adobe/aio-cli@9.0.0') + expect(exec.exec).toHaveBeenCalledWith('aio --version') + }) + + test('Failure - exec throws error', async () => { + const os = 'macos-latest' + const version = '90.1.1' + core.getInput.mockReturnValueOnce(os) + core.getInput.mockReturnValueOnce(version) + exec.exec.mockRejectedValue(new Error('No matching version found for @adobe/aio-cli@90.1.1')) + await jest.isolateModulesAsync(async () => { + await require('../index') // run the action + }) + expect(exec.exec).toHaveBeenCalledTimes(1) + expect(exec.exec).toHaveBeenCalledWith('npm install -g @adobe/aio-cli@90.1.1') + expect(core.setFailed).toHaveBeenCalledWith('No matching version found for @adobe/aio-cli@90.1.1') + }) +}) diff --git a/test/jest.setup.js b/test/jest.setup.js new file mode 100644 index 0000000..b29f32e --- /dev/null +++ b/test/jest.setup.js @@ -0,0 +1,31 @@ +/* +Copyright 2024 Adobe. All rights reserved. +This file is licensed to you 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 REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +jest.setTimeout(30000) + +const { stdout, stderr } = require('stdout-stderr') + +// trap console log +beforeEach(() => { + stdout.start() + stderr.start() + // change this if you need to see logs from stdout + stdout.print = false +}) + +afterEach(() => { + stdout.stop() + stderr.stop() +}) + +process.on('unhandledRejection', error => { + throw error +})