Skip to content

Commit

Permalink
Merge pull request #81 from cortex-lab/coveralls
Browse files Browse the repository at this point in the history
Coveralls
  • Loading branch information
k1o0 authored Feb 1, 2024
2 parents 7f4f57a + 2f163d6 commit 87e0384
Show file tree
Hide file tree
Showing 11 changed files with 874 additions and 54 deletions.
51 changes: 51 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
schedule:
- cron: '0 0 * * 0' # every Sunday at midnight
workflow_dispatch: # For manual triggering
push:
branches: [ master ]
pull_request:
branches: [ master, dev ]

env:
DOTENV_CONFIG_PATH: ./test/fixtures/.env.test

jobs:
build:
name: build ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false # Whether to stop execution of other instances
max-parallel: 4
matrix:
os: ["ubuntu-latest", "windows-latest"] # , "macos-latest"
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up node
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm install
- name: Run tests
run: |
npm run coverage
npx nyc report --reporter=lcovonly --reporter text
- name: Coveralls Parallel
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
flag-name: ${{ matrix.os }}
parallel: true
finish:
needs: build
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.github_token }}
parallel-finished: true
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
node_modules/*
.env
.pem
coverage/*
.nyc_output/*
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Changelog

## [Latest](https://github.com/cortex-lab/matlab-ci/commits/master) [3.1.0]
## [Latest](https://github.com/cortex-lab/matlab-ci/commits/master) [3.2.0]

## Modified

- if SIGTERM fails to end process(es) in under a minute, SIGKILL is sent

## Added

- git workflow
- set coveralls env vars

## [3.1.0]

## Modified

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LabCI
[![Build Status](https://travis-ci.com/cortex-lab/LabCI.svg?branch=master)](https://travis-ci.com/cortex-lab/matlab-ci)
[![Coverage](https://img.shields.io/badge/coverage-91.91-brightgreen)](https://img.shields.io/badge/coverage-72.35-yellowgreen)
![CI workflow](https://github.com/cortex-lab/LabCI/actions/workflows/tests.yml/badge.svg?branch=main)
[![Coverage](https://img.shields.io/badge/coverage-91.69-brightgreen)](https://img.shields.io/badge/coverage-72.35-yellowgreen)

A small set of modules written in Node.js for running automated tests of MATLAB and Python code in response to GitHub events. Also submits code coverage to the Coveralls API.

Expand Down Expand Up @@ -111,6 +111,10 @@ Your test script must do the following:
2. Save the results into the JSON cache file without duplication
3. For code coverage the script must either save the coverage directly, or export a Cobertura formatted XML file.

## Coveralls
Coverage information can be sent to coveralls.io using the [node-coveralls](https://github.com/nickmerwin/node-coveralls) package.
Adding `COVERALLS_REPO_TOKEN` to the .env file will cause the CI to set other dynamic env variables before running a pipeline.

## Built With

* [LocalTunnel](https://localtunnel.me) - A secure tunneling service
Expand Down
51 changes: 43 additions & 8 deletions lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,20 +324,48 @@ function getRepoPath(name) {
function startJobTimer(job, kill_children = false) {
const timeout = config.timeout || 8 * 60000; // How long to wait for the tests to run
return setTimeout(() => {
let log = _log.extend('job_timer');
console.log('Max test time exceeded');
log(kill_children ? 'Killing all processes' : 'Ending test process');
let pid = job._child.pid;
log('Killing process(es) for job #%g, pid = %d', job.id, pid);
job._child.kill();
if (kill_children) {
kill(pid);
}
if (kill_children) kill(pid);
// Give the processes 1 minute before sending a more aggressive signal
return setTimeout(() => {
if (job._child && job._child.exitCode == null) {
log('Failed to kill job process(es); sending SIGKILL (job #%g, pid = %d)', job.id, pid);
job._child.kill('SIGKILL');
if (kill_children) kill(pid, 'SIGKILL');
}
}, 60000)
}, timeout);
}


/**
* Set dynamic env variables for node-coveralls.
* NB: This does not support submodules.
* @param {Object} job - The Job with an associated process in the data field.
*/
function initCoveralls(job) {
const debug = log.extend('pipeline');
debug('Setting COVERALLS env variables');
process.env.COVERALLS_SERVICE_JOB_ID = job.id;
const envMap = {
'COVERALLS_SERVICE_NAME': job.data.context,
'COVERALLS_GIT_COMMIT': job.data.sha,
'COVERALLS_GIT_BRANCH': job.data.branch,
'CI_PULL_REQUEST': job.data.pull_number
};
for (let key in envMap) { // assign value or delete key
if (envMap[key]) { process.env[key] = envMap[key]; } else { delete process.env[key]; }
}
}

/**
* Build task pipeline. Takes a list of scripts/functions and builds a promise chain.
* @param {Object} job - The path of the repository
* @param {Object} job - The Job with an associated process in the data field.
* @returns {Promise} - The job routine
*/
async function buildRoutine(job) {
Expand Down Expand Up @@ -365,6 +393,9 @@ async function buildRoutine(job) {
});
const ops = config.shell ? {'shell': config.shell} : {};

// If environment variable COVERALLS_REPO_TOKEN is not null, set dynamic variables
if (process.env.COVERALLS_REPO_TOKEN) initCoveralls(job);

const init = () => debug('Executing pipeline for job #%g', job.id);
const routine = tasks.reduce(applyTask, Promise.resolve().then(init));
return routine
Expand Down Expand Up @@ -411,6 +442,8 @@ async function buildRoutine(job) {
clearTimeout(timer);
})
.on('close', (code, signal) => {
// FIXME Sometime close is not called after a timeout, maybe because
// the IO streams are kept open by some process?
const callback = (code === 0) ? resolve : reject;
const proc = {
code: code,
Expand All @@ -419,6 +452,8 @@ async function buildRoutine(job) {
stderr: stderr,
process: child
};
// Ensure there's an exitCode as the second kill timer checks for this
if (child.exitCode === null) child.exitCode = -1;
callback(proc);
});
job.child = child; // Assign the child process to the job
Expand Down Expand Up @@ -447,7 +482,7 @@ async function buildRoutine(job) {
message = `${errored.code} - Failed to spawn ${file}`;
}
// Check if the process was killed (we'll assume by the test timeout callback)
} else if (errored.process.killed || errored.signal === 'SIGTERM') {
} else if (errored.process.killed || ['SIGTERM', 'SIGKILL'].includes(errored.signal)) {
message = `Tests stalled after ~${(config.timeout / 60000).toFixed(0)} min`;
} else { // Error raised by process; dig through stdout for reason
debug('error from test function %s', file);
Expand Down Expand Up @@ -511,10 +546,10 @@ async function buildRoutine(job) {
*/
function computeCoverage(job) {
if (typeof job.data.coverage !== 'undefined' && job.data.coverage) {
console.log('Coverage already computed for job #' + job.id);
console.log('Coverage already computed for job #%g', job.id);
return;
}
console.log('Updating coverage for job #' + job.id);
console.log('Updating coverage for job #%g', job.id);
const xmlPath = path.join(config.dataPath, 'reports', job.data.sha, 'CoverageResults.xml');
const modules = listSubmodules(process.env.REPO_PATH);
return Coverage(xmlPath, job.data.repo, job.data.sha, modules).then(obj => {
Expand Down Expand Up @@ -719,5 +754,5 @@ module.exports = {
ensureArray, loadTestRecords, compareCoverage, computeCoverage, getBadgeData, log, shortID,
openTunnel, APIError, queue, partial, startJobTimer, updateJobFromRecord, shortCircuit, isSHA,
fullpath, strToBool, saveTestRecords, listSubmodules, getRepoPath, addParam, context2routine,
buildRoutine
buildRoutine, initCoveralls
};
Loading

0 comments on commit 87e0384

Please sign in to comment.