Ci setup (#2)

* chore: terminology change

* ci: basic

* ci: remove node 8.x

* chore: add semantic release

* ci: restrict codecov to n12

* ci: undo

* docs: spruce up main heading before release

* ci: secret name
This commit is contained in:
Marc Cataford 2020-02-29 19:38:31 -05:00 committed by GitHub
parent 218f8172ea
commit 98060385e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 3461 additions and 97 deletions

71
.github/workflows/nodejs.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: Node.js CI
on: [push]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x
- run: yarn
- run: yarn lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- run: yarn test:coverage
- name: Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
build:
runs-on: ubuntu-latest
needs: test
strategy:
matrix:
node-version: [10.x, 12.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- run: yarn build
release:
name: Release
runs-on: ubuntu-latest
if: github.ref == 'master'
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Node setup
uses: actions/setup-node@v1
with:
node-version: 12
- name: Prepare
run: yarn && yarn build
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: yarn semantic-release

View file

@ -1,4 +1,4 @@
# PackWatch # 📦 PackWatch 👀
> It ain't easy being tiny. > It ain't easy being tiny.

View file

@ -52,6 +52,7 @@
"mock-fs": "^4.11.0", "mock-fs": "^4.11.0",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"rimraf": "^3.0.2" "rimraf": "^3.0.2",
"semantic-release": "^17.0.4"
} }
} }

View file

@ -5,7 +5,7 @@ const PACKAGE_SIZE_PATT = /package size:\s+([0-9]+\.?[0-9]*\s+[A-Za-z]+)/g
const UNPACKED_SIZE_PATT = /unpacked size:\s+([0-9]+\.?[0-9]*\s+[A-Za-z]+)/g const UNPACKED_SIZE_PATT = /unpacked size:\s+([0-9]+\.?[0-9]*\s+[A-Za-z]+)/g
const SIZE_SUFFIX_PATT = /([A-Za-z]+)/ const SIZE_SUFFIX_PATT = /([A-Za-z]+)/
const SIZE_MAGNITUDE_PATT = /([0-9]+\.?[0-9]*)/ const SIZE_MAGNITUDE_PATT = /([0-9]+\.?[0-9]*)/
const DIGEST_FILENAME = '.packwatch.json' const MANIFEST_FILENAME = '.packwatch.json'
const FS_OPTIONS = { encoding: 'utf-8' } const FS_OPTIONS = { encoding: 'utf-8' }
@ -38,36 +38,36 @@ function getCurrentPackageStats() {
function getPreviousPackageStats() { function getPreviousPackageStats() {
try { try {
const currentDigest = readFileSync(DIGEST_FILENAME, FS_OPTIONS) const currentManifest = readFileSync(MANIFEST_FILENAME, FS_OPTIONS)
const parsedDigest = JSON.parse(currentDigest) const parsedManifest = JSON.parse(currentManifest)
return { return {
...parsedDigest, ...parsedManifest,
packageSizeBytes: convertSizeToBytes(parsedDigest.packageSize), packageSizeBytes: convertSizeToBytes(parsedManifest.packageSize),
unpackedSizeBytes: convertSizeToBytes(parsedDigest.unpackedSize), unpackedSizeBytes: convertSizeToBytes(parsedManifest.unpackedSize),
limitBytes: convertSizeToBytes(parsedDigest.limit), limitBytes: convertSizeToBytes(parsedManifest.limit),
} }
} catch (e) { } catch (e) {
return {} return {}
} }
} }
function createOrUpdateDigest({ previous, current, updateLimit = false }) { function createOrUpdateManifest({ previous, current, updateLimit = false }) {
const { limit } = previous || {} const { limit } = previous || {}
const { packageSize, unpackedSize } = current const { packageSize, unpackedSize } = current
const newDigest = { const newManifest = {
limit: updateLimit ? packageSize : limit || packageSize, limit: updateLimit ? packageSize : limit || packageSize,
packageSize: packageSize, packageSize: packageSize,
unpackedSize: unpackedSize, unpackedSize: unpackedSize,
} }
writeFileSync(DIGEST_FILENAME, JSON.stringify(newDigest)) writeFileSync(MANIFEST_FILENAME, JSON.stringify(newManifest))
} }
module.exports = { module.exports = {
createOrUpdateDigest, createOrUpdateManifest,
getPreviousPackageStats, getPreviousPackageStats,
getCurrentPackageStats, getCurrentPackageStats,
convertSizeToBytes, convertSizeToBytes,
DIGEST_FILENAME, MANIFEST_FILENAME,
} }

View file

@ -3,10 +3,10 @@
const { existsSync } = require('fs') const { existsSync } = require('fs')
const { const {
DIGEST_FILENAME, MANIFEST_FILENAME,
getCurrentPackageStats, getCurrentPackageStats,
getPreviousPackageStats, getPreviousPackageStats,
createOrUpdateDigest, createOrUpdateManifest,
} = require('./helpers') } = require('./helpers')
if (!existsSync('package.json')) { if (!existsSync('package.json')) {
@ -16,19 +16,19 @@ if (!existsSync('package.json')) {
process.exit(1) process.exit(1)
} }
const isUpdatingDigest = process.argv.includes('--update-digest') const isUpdatingManifest = process.argv.includes('--update-manifest')
const currentStats = getCurrentPackageStats() const currentStats = getCurrentPackageStats()
/* /*
* If there is no digest file yet, we can use the current package stats as * If there is no manifest file yet, we can use the current package stats as
* a base to build one. The current package size becomes the limit. * a base to build one. The current package size becomes the limit.
*/ */
if (!existsSync(DIGEST_FILENAME)) { if (!existsSync(MANIFEST_FILENAME)) {
createOrUpdateDigest({ current: currentStats }) createOrUpdateManifest({ current: currentStats })
console.log( console.log(
`📝 No digest to compare against! Current package stats written to ${DIGEST_FILENAME}!`, `📝 No Manifest to compare against! Current package stats written to ${MANIFEST_FILENAME}!`,
) )
console.log( console.log(
`Package size (${currentStats.packageSize}) adopted as new limit.`, `Package size (${currentStats.packageSize}) adopted as new limit.`,
@ -47,38 +47,38 @@ const {
const hasExceededLimit = packageSizeBytes > limitBytes const hasExceededLimit = packageSizeBytes > limitBytes
/* /*
* If we are updating the digest, we can write right away and terminate. * If we are updating the manifest, we can write right away and terminate.
*/ */
if (isUpdatingDigest) { if (isUpdatingManifest) {
createOrUpdateDigest({ createOrUpdateManifest({
previous: previousStats, previous: previousStats,
current: currentStats, current: currentStats,
updateLimit: true, updateLimit: true,
}) })
console.log( console.log(
`📝 Updated the digest! Package size: ${packageSize}, Limit: ${packageSize}`, `📝 Updated the manifest! Package size: ${packageSize}, Limit: ${packageSize}`,
) )
process.exit(0) process.exit(0)
} }
/* /*
* If there is a digest file and the current package busts its limit * If there is a manifest file and the current package busts its limit
* we signal it and terminate with an error. * we signal it and terminate with an error.
*/ */
if (hasExceededLimit) { if (hasExceededLimit) {
console.log( console.log(
`🔥🔥📦🔥🔥 Your package exceeds the limit set in ${DIGEST_FILENAME}! ${packageSize} > ${limit}`, `🔥🔥📦🔥🔥 Your package exceeds the limit set in ${MANIFEST_FILENAME}! ${packageSize} > ${limit}`,
) )
console.log( console.log(
'Either update the limit by using the --update-digest flag or trim down your packed files!', 'Either update the limit by using the --update-manifest flag or trim down your packed files!',
) )
process.exit(1) process.exit(1)
} }
/* /*
* If there is a digest file and the limit is not busted, we give * If there is a manifest file and the limit is not busted, we give
* the user some feedback on how the current package compares with * the user some feedback on how the current package compares with
* the previous one. * the previous one.
*/ */

View file

@ -7,11 +7,11 @@ jest.mock('child_process')
childProcess.spawnSync = jest.fn(() => ({ stderr: mockPackOutput })) childProcess.spawnSync = jest.fn(() => ({ stderr: mockPackOutput }))
const { const {
DIGEST_FILENAME, MANIFEST_FILENAME,
convertSizeToBytes, convertSizeToBytes,
getCurrentPackageStats, getCurrentPackageStats,
getPreviousPackageStats, getPreviousPackageStats,
createOrUpdateDigest, createOrUpdateManifest,
} = require('./helpers') } = require('./helpers')
const mockPackageSize = '1.1 kB' const mockPackageSize = '1.1 kB'
@ -83,7 +83,7 @@ describe('Helpers', () => {
const limit = '1 kB' const limit = '1 kB'
const limitBytes = 1000 const limitBytes = 1000
const mockReport = { packageSize, unpackedSize, limit } const mockReport = { packageSize, unpackedSize, limit }
mockFS({ [DIGEST_FILENAME]: JSON.stringify(mockReport) }) mockFS({ [MANIFEST_FILENAME]: JSON.stringify(mockReport) })
expect(getPreviousPackageStats()).toEqual({ expect(getPreviousPackageStats()).toEqual({
packageSize, packageSize,
@ -95,79 +95,79 @@ describe('Helpers', () => {
}) })
}) })
it('returns an empty digest if it fails to reads the digest file', () => { it('returns an empty manifest if it fails to reads the manifest file', () => {
mockFS({ mockFS({
[DIGEST_FILENAME]: 'not valid JSON', [MANIFEST_FILENAME]: 'not valid JSON',
}) })
expect(getPreviousPackageStats()).toEqual({}) expect(getPreviousPackageStats()).toEqual({})
}) })
}) })
describe('Creating or updating the digest', () => { describe('Creating or updating the manifest', () => {
const currentStats = { const currentStats = {
packageSize: '1 kB', packageSize: '1 kB',
unpackedSize: '10 kB', unpackedSize: '10 kB',
} }
const previousDigest = { const previousManifest = {
limit: '2 kB', limit: '2 kB',
packageSize: '1.5 kB', packageSize: '1.5 kB',
} }
it('creates a digest from the current data if no previous data is provided', () => { it('creates a anifest from the current data if no previous data is provided', () => {
mockFS({}) mockFS({})
createOrUpdateDigest({ current: currentStats }) createOrUpdateManifest({ current: currentStats })
const writtenDigest = readFileSync(DIGEST_FILENAME, { const writtenManifest = readFileSync(MANIFEST_FILENAME, {
encoding: 'utf-8', encoding: 'utf-8',
}) })
expect(JSON.parse(writtenDigest)).toEqual({ expect(JSON.parse(writtenManifest)).toEqual({
packageSize: currentStats.packageSize, packageSize: currentStats.packageSize,
unpackedSize: currentStats.unpackedSize, unpackedSize: currentStats.unpackedSize,
limit: currentStats.packageSize, limit: currentStats.packageSize,
}) })
}) })
it('updates the previous digest sizes if previous data exists', () => { it('updates the previous manifest sizes if previous data exists', () => {
mockFS({ mockFS({
[DIGEST_FILENAME]: JSON.stringify(previousDigest), [MANIFEST_FILENAME]: JSON.stringify(previousManifest),
}) })
createOrUpdateDigest({ createOrUpdateManifest({
current: currentStats, current: currentStats,
previous: previousDigest, previous: previousManifest,
updateLimit: false, updateLimit: false,
}) })
const writtenDigest = readFileSync(DIGEST_FILENAME, { const writtenManifest = readFileSync(MANIFEST_FILENAME, {
encoding: 'utf-8', encoding: 'utf-8',
}) })
expect(JSON.parse(writtenDigest)).toEqual({ expect(JSON.parse(writtenManifest)).toEqual({
packageSize: currentStats.packageSize, packageSize: currentStats.packageSize,
unpackedSize: currentStats.unpackedSize, unpackedSize: currentStats.unpackedSize,
limit: previousDigest.limit, limit: previousManifest.limit,
}) })
}) })
it('updates the previous digest sizes and limit if previous data exists and updateLimit is set', () => { it('updates the previous manifest sizes and limit if previous data exists and updateLimit is set', () => {
mockFS({ mockFS({
[DIGEST_FILENAME]: JSON.stringify(previousDigest), [MANIFEST_FILENAME]: JSON.stringify(previousManifest),
}) })
createOrUpdateDigest({ createOrUpdateManifest({
current: currentStats, current: currentStats,
previous: previousDigest, previous: previousManifest,
updateLimit: true, updateLimit: true,
}) })
const writtenDigest = readFileSync(DIGEST_FILENAME, { const writtenManifest = readFileSync(MANIFEST_FILENAME, {
encoding: 'utf-8', encoding: 'utf-8',
}) })
expect(JSON.parse(writtenDigest)).toEqual({ expect(JSON.parse(writtenManifest)).toEqual({
packageSize: currentStats.packageSize, packageSize: currentStats.packageSize,
unpackedSize: currentStats.unpackedSize, unpackedSize: currentStats.unpackedSize,
limit: currentStats.packageSize, limit: currentStats.packageSize,

3380
yarn.lock

File diff suppressed because it is too large Load diff