Skip to content

Commit

Permalink
Replace Travis with GitHub actions for CI (#27)
Browse files Browse the repository at this point in the history
* Add Prettier for code formatting
* Replace Travis with GitHub actions for CI

Signed-off-by: Liam McLoughlin <lmcloughlin@fitbit.com>
  • Loading branch information
Hexxeh committed Nov 4, 2020
1 parent 4368f26 commit 97ca45b
Show file tree
Hide file tree
Showing 17 changed files with 185 additions and 116 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- master

jobs:
build:
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
node_version: [10, 12, 14]
name: ${{ matrix.os }} / Node v${{ matrix.node_version }}
runs-on: ${{ matrix.os }}
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Restore yarn cache
uses: actions/cache@v1
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-node${{ matrix.node_version }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-node${{ matrix.node_version }}-yarn-
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Check code style (tslint)
run: yarn lint
- name: Check code style (Prettier)
run: yarn checkstyle
- name: Build
run: yarn build
- name: Run tests
run: yarn test --coverage
- name: Upload coverage
uses: coverallsapp/github-action@v1.1.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
5 changes: 5 additions & 0 deletions .huskyrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"hooks": {
"pre-commit": "lint-staged"
}
}
3 changes: 3 additions & 0 deletions .lintstagedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"*.{js,jsx,ts,tsx,json}": ["prettier --write", "tslint --fix"]
}
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/coverage/
/lib/
/mod/
__test__/
__snapshots__/
src/**/__test__
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"trailingComma": "all",
"arrowParens": "always",
"singleQuote": true
}
5 changes: 0 additions & 5 deletions .travis.yml

This file was deleted.

70 changes: 35 additions & 35 deletions bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import * as imageCodecTxi from '.';
import { join } from 'path';

const inputPNG = PNG.sync.read(
fs.readFileSync(
join(__dirname, 'src', '__test__', 'transparency-rgba.png'),
),
fs.readFileSync(join(__dirname, 'src', '__test__', 'transparency-rgba.png')),
);

const inputImage = {
Expand All @@ -21,35 +19,37 @@ const inputImage = {

const suite = new benchmark.Suite();

suite.add('RGBA8888', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGBA8888,
});
}).add('RGBA6666', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGBA6666,
});
})
.add('RGB565', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGB565,
});
})
.add('A8', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.A8,
});
})
.on('cycle', (event: any) => {
console.log(String(event.target));
console.log(`${(event.target.stats.mean * 1000).toFixed(2)} ms/run`);
})
.on('error', (event: any) => {
console.error(`Error running ${event.target.name}:`);
console.error(event.target.error);
})
.run({ async: true });
suite
.add('RGBA8888', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGBA8888,
});
})
.add('RGBA6666', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGBA6666,
});
})
.add('RGB565', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.RGB565,
});
})
.add('A8', () => {
imageCodecTxi.encode(inputImage, {
rle: 'auto',
outputFormat: imageCodecTxi.TXIOutputFormat.A8,
});
})
.on('cycle', (event: any) => {
console.log(String(event.target));
console.log(`${(event.target.stats.mean * 1000).toFixed(2)} ms/run`);
})
.on('error', (event: any) => {
console.error(`Error running ${event.target.name}:`);
console.error(event.target.error);
})
.run({ async: true });
11 changes: 3 additions & 8 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ module.exports = {
transform: {
'^.+\\.(ts|js)$': 'ts-jest',
},
moduleFileExtensions: [
'ts',
'js',
],
moduleFileExtensions: ['ts', 'js'],
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|js)$',
testPathIgnorePatterns: [
'<rootDir>/node_modules',
Expand All @@ -14,9 +11,7 @@ module.exports = {
'<rootDir>/mod',
],
testEnvironment: 'node',
coverageDirectory: "<rootDir>/coverage",
coverageDirectory: '<rootDir>/coverage',
collectCoverage: true,
collectCoverageFrom: [
"src/**/*.ts",
],
collectCoverageFrom: ['src/**/*.ts'],
};
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"homepage": "https://github.com/Fitbit/image-codec-txi#readme",
"scripts": {
"build": "rm -rf lib mod && tsc -p tsconfig.build.json && tsc -p tsconfig.module.json",
"lint": "tslint -c tslint.json -p tsconfig.json",
"lint": "tslint -c tslint.json -p tsconfig.json --format code-frame",
"checkstyle": "prettier --list-different \"**/*.{js,jsx,ts,tsx,json}\"",
"test": "npm run lint && jest",
"test:coveralls": "npm run lint && jest --coverage --coverageReporters=text-lcov | coveralls",
"prepublishOnly": "npm run test && npm run build",
Expand All @@ -32,10 +33,12 @@
"jest": "^25.1.0",
"microtime": "^3.0.0",
"pngjs": "^3.4.0",
"prettier": "^2.1.2",
"ts-jest": "^25.2.1",
"ts-node": "^8.7.0",
"tslint": "^6.1.0",
"tslint-config-airbnb": "^5.11.2",
"tslint-config-prettier": "^1.18.0",
"typescript": "^3.8.3"
}
}
3 changes: 1 addition & 2 deletions src/RunLengthEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ function comparePixel(a: Pixel, b: Pixel) {
const MAX_SECTION_LENGTH = 127;

export default class RunLengthEncoder {

private lastPixel: Pixel;
private lastPixelValid = false;
private pixelCount = 0;
Expand Down Expand Up @@ -49,7 +48,7 @@ export default class RunLengthEncoder {

private internalFlush() {
if (this.pixelCount > 0) {
let headerByte = this.willCompress ? (MAX_SECTION_LENGTH + 1) : 0;
let headerByte = this.willCompress ? MAX_SECTION_LENGTH + 1 : 0;
headerByte |= this.pixelCount & MAX_SECTION_LENGTH;
this.destination.array[this.headerIndex] = headerByte;
}
Expand Down
45 changes: 23 additions & 22 deletions src/encoder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ function checkImage(
height: uncompressed.height,
};

const actualCompressed = Buffer.from(encode(inputImage, { rle, outputFormat }));
const actualCompressed = Buffer.from(
encode(inputImage, { rle, outputFormat }),
);

let expectedCompressedPath = `${filename}.txi.${outputFormat.toLowerCase()}`;
if (rle !== false && expectRLEIsSmaller) expectedCompressedPath += '.rle';
Expand All @@ -43,45 +45,46 @@ function checkImage(

for (const withRLE of [true, false]) {
describe(`with RLE encoding ${withRLE ? 'enabled' : 'disabled'}`, () => {
it('converts an RGB PNG to RGBA8888', () => checkImage('rgb_image', withRLE));
it('converts an RGB PNG to RGBA8888', () =>
checkImage('rgb_image', withRLE));
it('converts an RGB PNG to RGB565', () =>
checkImage('rgb_image', withRLE, TXIOutputFormat.RGB565));
it('converts an RGB PNG to RGBA6666', () =>
checkImage('rgb_image', withRLE, TXIOutputFormat.RGBA6666));
it('converts a paletted PNG', () => checkImage('palette', withRLE));
it('converts a 1-bit PNG', () => checkImage('1bit', withRLE, TXIOutputFormat.A8));
it('converts a 1-bit PNG', () =>
checkImage('1bit', withRLE, TXIOutputFormat.A8));
it('converts a very small image', () => checkImage('tiny', withRLE));
it('converts an image that exceeds the worst case size when padded',
() => checkImage('rle_increases_size', withRLE));
it('converts a PNG that leaves no RLE leftover bytes to flush',
() => checkImage('rle_no_leftovers', withRLE));
it('converts an image that is larger when RLE encoded than unencoded',
() => checkImage('greyscale_bands', withRLE, TXIOutputFormat.A8));
it('converts an image that exceeds the worst case size when padded', () =>
checkImage('rle_increases_size', withRLE));
it('converts a PNG that leaves no RLE leftover bytes to flush', () =>
checkImage('rle_no_leftovers', withRLE));
it('converts an image that is larger when RLE encoded than unencoded', () =>
checkImage('greyscale_bands', withRLE, TXIOutputFormat.A8));
});
}

it('returns the smaller output if RLE mode is set to auto',
() => checkImage('greyscale_bands', 'auto', TXIOutputFormat.A8, false));
it('returns the smaller output if RLE mode is set to auto', () =>
checkImage('greyscale_bands', 'auto', TXIOutputFormat.A8, false));

const PNG_SUITE_DIR = 'PngSuite-2017jul19';

describe('readPNG', () => {
const pngSuite = fs.readdirSync(testResourcePath(PNG_SUITE_DIR))
.filter(file => file.endsWith('.png'));
const validPNGs = pngSuite.filter(file => !file.startsWith('x'));
const corruptPNGs = pngSuite.filter(file => file.startsWith('x'));
const pngSuite = fs
.readdirSync(testResourcePath(PNG_SUITE_DIR))
.filter((file) => file.endsWith('.png'));
const validPNGs = pngSuite.filter((file) => !file.startsWith('x'));
const corruptPNGs = pngSuite.filter((file) => file.startsWith('x'));

describe('given a valid PNG file', () => {
it.each(validPNGs)('reads %s', (vector) => {
expect(readPNG(loadTestResource(PNG_SUITE_DIR, vector)))
.toBeDefined();
expect(readPNG(loadTestResource(PNG_SUITE_DIR, vector))).toBeDefined();
});
});

describe('given a corrupt PNG file', () => {
it.each(corruptPNGs)('rejects %s', (vector) => {
expect(() => readPNG(loadTestResource(PNG_SUITE_DIR, vector)))
.toThrow();
expect(() => readPNG(loadTestResource(PNG_SUITE_DIR, vector))).toThrow();
});
});

Expand All @@ -103,8 +106,6 @@ describe('readPNG', () => {

describe('given an ArrayBuffer', () => {
it('reads the file', () =>
expect(readPNG(loadTestResource('tiny.png')))
.toBeDefined(),
);
expect(readPNG(loadTestResource('tiny.png'))).toBeDefined());
});
});
Loading

0 comments on commit 97ca45b

Please sign in to comment.