Skip to content

Commit

Permalink
Fix: commit hidden test file
Browse files Browse the repository at this point in the history
  • Loading branch information
pustovitDmytro committed Apr 26, 2021
1 parent bf16986 commit 043dd76
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 182 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defaults: &defaults
resource_class: small
docker:
- image: circleci/node:14
cache-defaults: &cache-defaults
Expand Down
260 changes: 162 additions & 98 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@
"dependencies": {
"archiver": "^5.3.0",
"axios": "^0.21.1",
"globby": "^11.0.3",
"libnpmversion": "^1.2.0",
"livr": "^2.3.3",
"livr-extra-rules": "^1.2.1"
"livr-extra-rules": "^1.2.1",
"tar-fs": "^2.1.1"
}
}
8 changes: 4 additions & 4 deletions src/Error.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ export class VALIDATION_FAILED extends SemanticReleaseHerokuError {

export class API_ERROR extends SemanticReleaseHerokuError {
get message() {
const message = this.payload.toString();
const inner = this.payload?.response?.data;
const messages = [ this.payload.toString() ];
const inner = this.payload.response?.data;

if (inner) return [ message, JSON.stringify(inner) ].join(' ');
if (inner) messages.push(JSON.stringify(inner));

return message;
return messages.join(' ');
}
}
84 changes: 25 additions & 59 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,46 @@
import os from 'os';
import path from 'path';
import archiver from 'archiver';
import tar from 'tar-fs';
import fs from 'fs-extra';
import uuid from 'uuid';
import LIVR from 'livr';
import extraRules from 'livr-extra-rules';
import { VALIDATION_FAILED } from './Error';

const globby = require('globby');

LIVR.Validator.registerDefaultRules(extraRules);

export async function tarball(src, trg = os.tmpdir(), options = {}) {
const { exclude = [ 'node_modules' ], include = [] } = options;
const outFile = `${trg}/${uuid.v4()}.tar`;
const output = fs.createWriteStream(outFile);
const archive = archiver('tar', {});
const ignore = options.ignore
|| await gitignore(path.join(src, '.herokuignore'))
|| await gitignore(path.join(src, '.gitignore'))
|| [ '.git/**', 'node_modules/**' ];
const isGitIgnored = await globby.gitignore({
cwd : src,
ignore : include
});
const isNotExcluded = await globby('**', {
followSymbolicLinks : false,
onlyFiles : false,
expandDirectories : true,
dot : true,
cwd : src,
ignore : exclude
});

const pack = tar.pack(src, {
ignore(name) {
return isGitIgnored(name) || !isNotExcluded.includes(path.relative(src, name));
}
});

const promise = new Promise((resolve, reject) => {
await new Promise((resolve, reject) => {
output.on('close', resolve);
output.on('end', resolve);
archive.on('error', reject);
pack.on('error', reject);
pack.pipe(output);
});

archive.on('warning', e => console.error(e));
archive.pipe(output);
archive.glob('**', { cwd: src, ignore, matchBase: true });
// archive.directory(src, false);
archive.finalize();

await promise;

return outFile;
}

Expand Down Expand Up @@ -64,46 +73,3 @@ export function validate(data, rules) {

return result;
}

async function gitignore(filePath) {
if (!await fs.exists(filePath)) return;
const content = await fs.readFile(filePath, { encoding: 'utf8' });

return gitignoreToGlob(content.split(/\r?\n/).map(s => s.trim()));
}

export function gitignoreToGlob(lines) {
return lines
.filter((pattern) => !!pattern && pattern[0] !== '#') // Filter out empty lines and comments.
// Return pairt [ignoreFlag, pattern], we'll concatenate it later.
.map(pattern =>
pattern[0] === '!' ? [ '!', pattern.substring(1) ] : [ '', pattern ],
// Filter out hidden files/directories (i.e. starting with a dot).
).filter((patternPair) => {
const pattern = patternPair[1];

return (
pattern.indexOf('/.') === -1 && pattern.indexOf('.') !== 0
);
}).map((patternPair) => {
const pattern = patternPair[1];

if (pattern[0] !== '/') {
return [
patternPair[0],
`**/${pattern}`
];
}

return [ patternPair[0], pattern.substring(1) ];
// We don't know whether a pattern points to a directory or a file and we need files.
// Therefore, include both `pattern` and `pattern/**` for every pattern in the array.
}).reduce((result, patternPair) => {
const pattern = patternPair.join('');

result.push(pattern);
result.push(`${pattern}/**`);

return result;
}, []);
}
Binary file added tests/fixtures/gitignore.tar
Binary file not shown.
1 change: 1 addition & 0 deletions tests/fixtures/gitignore/.hidden/in_git
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1
Binary file added tests/fixtures/txt_file.tar
Binary file not shown.
6 changes: 6 additions & 0 deletions tests/mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ class MOCK_API extends API {
'put_url' : 'http://ek.tr/ibebowohu'
} });
}
if (opts.url.match('conncection-error')) {
throw axiosError(opts, {
message : 'Not Found',
code : 404
});
}

return axiosResponse(1);
}
Expand Down
16 changes: 16 additions & 0 deletions tests/package/verifyConditions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,19 @@ test('Positive: valid config', async function () {
}
);
});

test('Negative: cant connect heroku api', async function () {
await checkError(
verifyConditions.call(
{},
{ name: 'conncection-error' },
{
cwd : process.cwd(),
env : { HEROKU_API_KEY: 'c5977e4b-970e-4965-aa69-85e781ab488c' },
logger : console
},
),
'API_ERROR',
'Not Found'
);
});
48 changes: 45 additions & 3 deletions tests/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import path from 'path';
import { assert } from 'chai';
import md5 from 'md5';
import fs from 'fs-extra';
import tar from 'tar-fs';
import uuid from 'uuid';
import { tmpFolder } from './constants';

export async function checkError(promise, type, message) {
try {
Expand All @@ -12,8 +16,46 @@ export async function checkError(promise, type, message) {
}
}

export async function checkMD5(file, hash) {
const buff = await fs.readFile(file);
async function extractTar(tarPath) {
const tmp = path.join(tmpFolder, uuid.v4());
const extract = tar.extract(tmp);

assert.equal(md5(buff), hash, `${Buffer.byteLength(buff)}: ${buff.toString()}`);
await new Promise((res, rej) => {
extract.on('finish', res);
extract.on('error', rej);
fs.createReadStream(tarPath).pipe(extract);
});

return tmp;
}

export async function getFiles(dir) {
const subdirs = await fs.readdir(dir);
const files = await Promise.all(subdirs.map(async (subdir) => {
const res = path.resolve(dir, subdir);

return (await fs.stat(res)).isDirectory() ? getFiles(res) : res;
}));

return files.reduce((a, f) => a.concat(f), []);
}

assert.isTarEqual = async function (actualPath, expectedPath) {
const actTmp = await extractTar(actualPath);
const expTmp = await extractTar(expectedPath);

const actFiles = await getFiles(actTmp);
const expFiles = await getFiles(expTmp);

const relActFiles = actFiles.map(f => path.relative(actTmp, f));
const relExpFiles = expFiles.map(f => path.relative(expTmp, f));

assert.deepEqual(relActFiles.sort(), relExpFiles.sort());

await Promise.all(relExpFiles.map(async f => {
const expBuff = await fs.readFile(path.join(expTmp, f));
const actBuff = await fs.readFile(path.join(actTmp, f));

assert.equal(md5(actBuff), md5(expBuff), f);
}));
};
32 changes: 15 additions & 17 deletions tests/utils/tar.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import path from 'path';
import { assert } from 'chai';
import fs from 'fs-extra';
import { _load } from '../entry';
import Test, { fixturesFolder, tmpFolder } from '../Test';
import { checkMD5 } from '../utils';
import '../utils';

const { tarball, gitignoreToGlob } = _load('utils');
const { tarball } = _load('utils');
const t = new Test();

suite('tar');
Expand All @@ -19,32 +20,29 @@ test('Positive: pack folder default ignore', async function () {
tmpFolder
);

await checkMD5(file, '1c018477609a1158276d4eb5297e3c3b');
await assert.isTarEqual(file, path.join(fixturesFolder, 'txt_file.tar'));
});


test('Positive: pack folder with .gitignore', async function () {
await fs.move(
path.join(fixturesFolder, 'gitignore', '.herokuignore'),
path.join(fixturesFolder, 'gitignore', '.gitignore')
);

const file = await tarball(
path.join(fixturesFolder, 'gitignore'),
tmpFolder
);

await checkMD5(file, 'befa71531e37e0b757be155d5e63a8f4');
});


test('Positive: gitignoreToGlob', async function () {
[
[ 'dir', [ '**/dir', '**/dir/**' ] ],
[ '!dir', [ '!**/dir', '!**/dir/**' ] ],
[ '/dir', [ 'dir', 'dir/**' ] ]
].forEach(([ gitignore, glob ]) => {
const actual = gitignoreToGlob([ gitignore ]);
await fs.move(
path.join(fixturesFolder, 'gitignore', '.gitignore'),
path.join(fixturesFolder, 'gitignore', '.herokuignore')
);

assert.deepEqual(actual, glob);
});
await assert.isTarEqual(file, path.join(fixturesFolder, 'gitignore.tar'));
});

after(async function () {
// await t.cleanTmpFolder();
await t.cleanTmpFolder();
});

0 comments on commit 043dd76

Please sign in to comment.