diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml new file mode 100644 index 0000000..b7984cf --- /dev/null +++ b/.github/workflows/node-ci.yml @@ -0,0 +1,144 @@ +name: Node CI + +on: + workflow_call: + # Inputs the workflow accepts. + + inputs: + node-version: + type: string + description: "Node version" + required: true + + package-manager: + type: string + description: "The package manager to use (npm or yarn)" + required: true + + cache-lockfile-path: + type: string + description: "Path to the lockfile that will be used as cache key" + default: "" + + working-directory-scripts: + type: string + description: "Working directory when running npm scripts" + default: "." + + working-directory-install: + type: string + description: "Working directory when installing dependencies. default = working-directory-scripts" + default: "" + + lint-script: + type: string + description: "Lint npm script name" + default: "lint" + + pre-build-command: + type: string + description: "Pre build command" + default: "exit 0" + + build-script: + type: string + description: "Build npm script name" + default: "build" + + post-install-command: + type: string + description: "Post install command" + default: "exit 0" + + test-script: + type: string + description: "Test npm script name" + default: "test" + + skip-lint: + type: boolean + description: "Skip lint" + default: false + skip-build: + type: boolean + description: "Skip build" + default: false + skip-test: + type: boolean + description: "Skip test" + default: true + + test-coverage-path: + type: string + description: "Test coverage files path (leave empty to disable uploading)" + default: "" + + build-artifacts-path: + type: string + description: "Build artifacts path (leave empty to disable uploading)" + default: "" + +jobs: + lint: + runs-on: ubuntu-latest + if: inputs.skip-lint != true + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: kir-dev/automations/actions/node-ci@node-ci + with: + node-version: ${{ inputs.node-version }} + package-manager: ${{ inputs.package-manager }} + cache-lockfile-path: ${{ inputs.cache-lockfile-path }} + working-directory-scripts: ${{ inputs.working-directory-scripts }} + working-directory-install: ${{ inputs.working-directory-install }} + lint-script: ${{ inputs.lint-script }} + post-install-command: ${{ inputs.post-install-command }} + skip-build: true + skip-test: true + skip-lint: false + test: + runs-on: ubuntu-latest + if: inputs.skip-test != true + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: kir-dev/automations/actions/node-ci@node-ci + with: + node-version: ${{ inputs.node-version }} + package-manager: ${{ inputs.package-manager }} + cache-lockfile-path: ${{ inputs.cache-lockfile-path }} + working-directory-scripts: ${{ inputs.working-directory-scripts }} + working-directory-install: ${{ inputs.working-directory-install }} + post-install-command: ${{ inputs.post-install-command }} + test-script: ${{ inputs.test-script }} + skip-lint: true + skip-build: true + skip-test: false + test-coverage-path: ${{ inputs.test-coverage-path }} + build: + if: inputs.skip-build != true + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - uses: kir-dev/automations/actions/node-ci@node-ci + with: + node-version: ${{ inputs.node-version }} + package-manager: ${{ inputs.package-manager }} + cache-lockfile-path: ${{ inputs.cache-lockfile-path }} + working-directory-scripts: ${{ inputs.working-directory-scripts }} + working-directory-install: ${{ inputs.working-directory-install }} + pre-build-command: ${{ inputs.pre-build-command }} + build-script: ${{ inputs.build-script }} + post-install-command: ${{ inputs.post-install-command }} + skip-lint: true + skip-test: true + skip-build: false + build-artifacts-path: ${{ inputs.build-artifacts-path }} diff --git a/actions/node-ci/action.yml b/actions/node-ci/action.yml new file mode 100644 index 0000000..7ddcaf6 --- /dev/null +++ b/actions/node-ci/action.yml @@ -0,0 +1,141 @@ +name: "Node CI" +description: "Run install, lint, build and test" + +inputs: + node-version: + description: "Node version" + required: true + + package-manager: + description: "The package manager to use (npm or yarn)" + required: true + + cache-lockfile-path: + description: "Path to the lockfile that will be used as cache key" + default: "" + + working-directory-scripts: + description: "Working directory when running npm scripts" + default: "./" + + working-directory-install: + description: "Working directory when installing dependencies. default = working-directory-scripts" + default: "" + + lint-script: + description: "Lint npm script name" + default: "lint" + pre-build-command: + description: "Pre build command" + default: "exit 0" + build-script: + description: "Build npm script name" + default: "build" + post-install-command: + description: "Post install command" + default: "exit 0" + test-script: + description: "Test npm script name" + default: "test" + + skip-install: + description: "Skip install" + default: "false" + skip-lint: + description: "Skip lint" + default: "false" + skip-build: + description: "Skip build" + default: "false" + skip-test: + description: "Skip test" + default: "false" + + test-coverage-path: + description: "Test coverage files path (leave empty to disable uploading)" + default: "" + + build-artifacts-path: + description: "Build artifacts path (leave empty to disable uploading)" + default: "" + +runs: + using: "composite" + steps: + - name: On unsupported package manager + if: inputs.package-manager != 'npm' && inputs.package-manager != 'yarn' + shell: bash + run: |- + echo "Unsupported package manager: ${{ inputs.package-manager }}" + exit 1 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: ${{ inputs.package-manager }} + cache-dependency-path: ${{ inputs.cache-lockfile-path }} + + - name: Install dependencies (with npm) + shell: bash + if: inputs.skip-install == 'false' && inputs.package-manager == 'npm' + run: npm ci + working-directory: ${{ inputs.working-directory-install || inputs.working-directory-scripts }} + + - name: Install dependencies (with yarn) + shell: bash + if: inputs.skip-install == 'false' && inputs.package-manager == 'yarn' + run: yarn install --frozen-lockfile + working-directory: ${{ inputs.working-directory-install || inputs.working-directory-scripts }} + + - name: Lint + if: inputs.skip-lint == 'false' + shell: bash + run: |- + set -euo pipefail + ${{ inputs.package-manager }} run ${{ inputs.lint-script }} + working-directory: ${{ inputs.working-directory-scripts }} + + - name: Build + if: inputs.skip-build == 'false' + shell: bash + run: |- + set -euo pipefail + ${{ inputs.package-manager }} run ${{ inputs.build-script }} + working-directory: ${{ inputs.working-directory-scripts }} + + - name: Test + id: test + if: inputs.skip-test == 'false' + env: + LOG_FILE: ${{ runner.temp }}/test-output.txt + shell: bash + run: |- + set -euo pipefail + ${{ inputs.package-manager }} run ${{ inputs.test-script }} > $LOG_FILE + echo "log-file=$LOG_FILE" >> $GITHUB_OUTPUT + working-directory: ${{ inputs.working-directory-scripts }} + + - name: Comment Test results to action + if: steps.test.outputs.log-file != '' && always() + shell: bash + run: cat ${{ steps.test.outputs.log-file }} >> $GITHUB_STEP_SUMMARY + continue-on-error: true + + - name: Upload coverage + if: inputs.skip-test == 'false' && inputs.test-coverage-path != '' && always() + uses: actions/upload-artifact@v4 + with: + name: coverage + path: ${{ inputs.test-coverage-path}} + retention-days: 7 + if-no-files-found: error + + - name: Upload build + if: inputs.skip-build == 'false' && inputs.build-artifacts-path != '' && always() + uses: actions/upload-artifact@v4 + with: + name: build + path: ${{ inputs.build-artifacts-path }} + retention-days: 7 + if-no-files-found: error