Continuous Integration (CI)
A great use case for secco is to copy over changes from your package to a test site used for End-to-End testing. This way you can verify that your published and built package works consistently.
In this guide you’ll learn which secco CLI options to use and how to set up your CI workflow.
Prerequisites
Let’s say you have the following setup:
Directorydist
- index.js
Directorye2e-tests
Directorykitchen-sink/
- …
Directoryscripts
- e2e-test.sh
Directorysrc
- index.ts
- package.json
Your source file lives inside src
and is compiled to the dist
folder. You created one of many test sites for End-to-End testing purposes inside e2e-tests
.
Now, inside your CI you want to copy e2e-tests/kitchen-sink
to a temporary folder to isolate it. Afterwards your latest changes from dist
are copied to that temporary folder through installation.
Scripts
For the purpose of this guide a couple of script were chosen to explain the necessary steps. You can use any tool you like though, for example execa’s scripts interface.
Generally speaking, you’ll want to run the script like so:
- Figure out the absolute path to your source and set the
SECCO_SOURCE_PATH
environment variable - Create a temporary folder (e.g. inside the system’s
tmp
folder) - Install the
secco
CLI throughnpm install -g secco@latest
- Copy the contents of your test site into the temporary folder
- Navigate into the new temporary folder
- Run
secco --force-verdaccio --scan-once
inside your e2e test site - Run the test suite in your e2e test site
Bash
#!/bin/bashset -e # Bail on errors
# Setup variables and env vars
TEST_PATH=$1 # First script argTEST_COMMAND="${2:-npm run test}" # Second script arg# The YOUR_CI_WORKING_DIRECTORY depends on how/where you run this scripteval SOURCE_PATH=${YOUR_CI_WORKING_DIRECTORY:-../..}TMP_LOCATION=$(mktemp -d);# secco needs the SECCO_SOURCE_PATH environment variableexport SECCO_SOURCE_PATH=$SOURCE_PATH
# Create the temporary folders
mkdir -p $TMP_LOCATION/$TEST_PATHTMP_TEST_LOCATION=$TMP_LOCATION/$TEST_PATHmkdir -p $TMP_TEST_LOCATION
# Install the secco CLI
(command -v sudo && sudo npm install -g secco@latest) || npm install -g secco@latest
# Copy the test suite into the temporary location to isolate it
echo "Copy $TEST_PATH into $TMP_LOCATION to isolate test"cp -Rv $TEST_PATH/. $TMP_TEST_LOCATION
cd "$TMP_TEST_LOCATION"
# Run the secco CLI once
secco --force-verdaccio --scan-once
# Run the End-to-End tests
sh -c "$TEST_COMMAND"
zx
You can use google/zx
to write a script.
Install the necessary dependencies:
npm install zx @actions/core
Create a new file, e.g. called install-site-in-isolation.mjs
:
#!/usr/bin/env zx
import { cp, mkdir, mkdtemp } from 'node:fs/promises'import { tmpdir } from 'node:os'import { join } from 'node:path'
import * as core from '@actions/core'import { $, argv, cd, chalk } from 'zx'
try { // Setup variables and environment variables const SITE_PATH = argv._[0] const ROOT_PATH = new URL('../', import.meta.url).pathname const FULL_SITE_PATH = join(ROOT_PATH, SITE_PATH) const TMP_FOLDER = await mkdtemp(join(tmpdir(), 'secco-site-')) const FULL_TMP_FOLDER = join(TMP_FOLDER, SITE_PATH) process.env.SECCO_SOURCE_PATH = ROOT_PATH process.env.FORCE_COLOR = '1'
core.debug(`Path variables:
SITE_PATH: ${SITE_PATH}ROOT_PATH: ${ROOT_PATH}FULL_SITE_PATH: ${FULL_SITE_PATH}TMP_FOLDER: ${TMP_FOLDER}FULL_TMP_FOLDER: ${FULL_TMP_FOLDER}`)
// Installing secco await core.group('Installing secco (if not already installed)', async () => { await $`command -v secco || (command -v sudo && sudo npm install -g secco@latest) || npm install -g secco@latest` })
// Create temporary folder setup await mkdir(FULL_TMP_FOLDER, { recursive: true })
// Copy the site into the temporary location to isolate it core.info(`Copying ${chalk.bold(SITE_PATH)} into ${chalk.bold(FULL_TMP_FOLDER)}`) await cp(FULL_SITE_PATH, FULL_TMP_FOLDER, { recursive: true })
await core.group('Installing dependencies through secco', async () => { cd(FULL_TMP_FOLDER) await $`secco --force-verdaccio --scan-once` })
core.exportVariable('FULL_TMP_FOLDER', FULL_TMP_FOLDER)}catch (e) { // Bail on errors core.setFailed(`Script failed with error: ${e}`)}
This script won’t run your tests yet, you’d need to add the functionality to the script or use the exported environment variable FULL_TMP_FOLDER
for later steps (GitHub Actions).
CI workflows
CircleCI
You could run the bash script inside CircleCI like so:
commands: e2e-test: parameters: test_path: type: string test_command: type: string default: npm run test steps: - checkout - run: name: Run e2e tests command: ./scripts/e2e-test.sh "<< parameters.test_path >>" "<< parameters.test_command >>"
GitHub Actions
You could use the zx script inside GitHub actions like so:
name: E2E Testson: pull_request
jobs: test: runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v4 with: ref: refs/pull/${{ github.event.issue.number }}/head
- name: Install dependencies & setup repo run: # Your setup
- name: Build packages run: # Your build setup
- name: Install site in isolation run: node scripts/install-site-in-isolation.mjs e2e-tests/kitchen-sink
- name: Run tests run: | cd $FULL_TMP_FOLDER npm run test
You’ll probably want to adapt the workflow to use matrix so that you can run multiple tests (if you have more than one).