Skip to content

Commit

Permalink
Merge pull request #31 from humanitec/ts
Browse files Browse the repository at this point in the history
chore: port to typescript & basic test
  • Loading branch information
johanneswuerbach authored Nov 29, 2022
2 parents b210ea8 + 4ca155d commit 9a1eddc
Show file tree
Hide file tree
Showing 16 changed files with 12,838 additions and 3,835 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"google"
],
"globals": {
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ jobs:
test:
runs-on: ubuntu-latest

env:
HUMANITEC_ORG: ${{ secrets.HUMANITEC_ORG }}
HUMANITEC_TOKEN: ${{ secrets.HUMANITEC_TOKEN }}

strategy:
matrix:
node-version: [16.x, 18.x]
Expand All @@ -18,4 +22,5 @@ jobs:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run package
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,11 @@ uses: humanitec/build-push-to-humanitec@v1
humanitec-token: ${{ secrets.HUMANITEC_TOKEN }}
organization: awesome-company
```


## Development

Running the tests requires an Humanitec account. Once this is created, the following environment variables need to be configure:

* `HUMANITEC_ORG`
* `HUMANITEC_TOKEN`
110 changes: 110 additions & 0 deletions action.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import {describe, expect, test, beforeEach, afterAll} from '@jest/globals';
import {join as pathJoin} from 'node:path';
import {runAction} from './action';
import {randomBytes} from 'crypto';
import fetch from 'node-fetch';
import {mkdir} from 'node:fs/promises';

// Emulate https://github.com/actions/toolkit/blob/819157bf8/packages/core/src/core.ts#L128
const setInput = (name: string, value: string): void => {
process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] = value;
};

const fixtures = pathJoin(__dirname, './fixtures');

const ensureEnv = (name: string): string => {
const val = process.env[name];
if (!val) {
throw new Error(`Required environment variables ${name} is empty.`);
}

return val;
};

const token = ensureEnv('HUMANITEC_TOKEN');
const orgId = ensureEnv('HUMANITEC_ORG');

const tenMinInMs = 10 * 60 * 1000;

describe('action', () => {
let repo: string;
let commit: string;


afterAll(async () => {
const res = await fetch(
`https://api.humanitec.io/orgs/${orgId}/artefacts?type=container`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'User-Agent': 'gh-action-build-push-to-humanitec/latest',
},
});

expect(res.status).toBe(200);

const body = await res.json();

for (const artefact of body) {
if (!artefact.name.startsWith(`registry.humanitec.io/${orgId}/test-`)) {
continue;
}

if (Date.now() - Date.parse(artefact.createdAt) < tenMinInMs) {
continue;
}

const res = await fetch(
`https://api.humanitec.io/orgs/${orgId}/artefacts/${artefact.id}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'User-Agent': 'gh-action-build-push-to-humanitec/latest',
},
});
expect(res.status).toBe(204);
}
});

beforeEach(async () => {
await mkdir(pathJoin(fixtures, '.git'));

setInput('humanitec-token', token);
setInput('organization', orgId);
setInput('context', '.');

commit = randomBytes(20).toString('hex');
repo = `test-${randomBytes(20).toString('hex')}`;

process.env['GITHUB_WORKSPACE'] = fixtures;
process.env['GITHUB_SHA'] = commit;
process.env['GITHUB_REPOSITORY'] = repo;
});

test('succeeds', async () => {
await runAction();
expect(process.exitCode).toBeFalsy;

const res = await fetch(
`https://api.humanitec.io/orgs/${orgId}/artefact-versions`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
'User-Agent': 'gh-action-build-push-to-humanitec/latest',
},
});

expect(res.status).toBe(200);

const body = await res.json();

expect(body).toEqual(
expect.arrayContaining(
[expect.objectContaining({commit: commit})],
),
);
});
});
33 changes: 14 additions & 19 deletions index.js → action.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
const docker = require('./docker');
const humanitecFactory = require('./humanitec');
const fs = require('fs');
const core = require('@actions/core');
import * as docker from './docker';
import {humanitecFactory} from './humanitec';

import {existsSync} from 'node:fs';
import * as core from '@actions/core';

/**
* Performs the GitHub action.
*/
async function runAction() {
export async function runAction() {
// Get GitHub Action inputs
const token = core.getInput('humanitec-token', {required: true});
const orgId = core.getInput('organization', {required: true});
const imageName = core.getInput('image-name') || process.env.GITHUB_REPOSITORY.replace(/.*\//, '');
const imageName = core.getInput('image-name') || (process.env.GITHUB_REPOSITORY || '').replace(/.*\//, '');
const context = core.getInput('context') || core.getInput('dockerfile') || '.';
const file = core.getInput('file') || '';
const registryHost = core.getInput('humanitec-registry') || 'registry.humanitec.io';
const apiHost = core.getInput('humanitec-api') || 'api.humanitec.io';
const tag = core.getInput('tag') || '';
const commit = process.env.GITHUB_SHA;
const commit = process.env.GITHUB_SHA || '';
const autoTag = /^\s*(true|1)\s*$/i.test(core.getInput('auto-tag'));
const additionalDockerArguments = core.getInput('additional-docker-arguments') || '';

const ref = process.env.GITHUB_REF;
if (!fs.existsSync(`${process.env.GITHUB_WORKSPACE}/.git`)) {
const ref = process.env.GITHUB_REF || '';
if (!existsSync(`${process.env.GITHUB_WORKSPACE}/.git`)) {
core.error('It does not look like anything was checked out.');
core.error('Did you run a checkout step before this step? ' +
'http:/docs.humanitec.com/connecting-your-ci#github-actions');
core.setFailed('No .git directory found in workspace.');
return;
}

if (file != '' && !fs.existsSync(file)) {
if (file != '' && !existsSync(file)) {
core.error(`Cannot find file ${file}`);
core.setFailed('Cannot find file.');
return;
}

if (!fs.existsSync(context)) {
if (!existsSync(context)) {
core.error(`Context path does not exist: ${context}`);
core.setFailed('Context path does not exist.');
return;
Expand All @@ -59,10 +60,10 @@ async function runAction() {
return;
}

process.chdir(process.env.GITHUB_WORKSPACE);
process.chdir((process.env.GITHUB_WORKSPACE || ''));

let version = '';
if (autoTag && ref.includes('\/tags\/')) {
if (autoTag && ref.includes('/tags/')) {
version = ref.replace(/.*\/tags\//, '');
} else if (tag) {
version = tag;
Expand Down Expand Up @@ -100,9 +101,3 @@ async function runAction() {
return;
}
}

runAction().catch((e) => {
core.error('Action failed');
core.error(`${e.name} ${e.message}`);
core.setFailed(`${e.name} ${e.message}`);
});
70 changes: 0 additions & 70 deletions chunk.js

This file was deleted.

68 changes: 68 additions & 0 deletions chunk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const args = (str: string): string[] => {
const args = [];
str = str.trim();
let currentArg = '';
for (let i = 0; i < str.length; i++) {
switch (str[i]) {
case '\'':
const endQuoteIndex = str.indexOf('\'', i+1);
if (endQuoteIndex < 0) {
throw 'single quote not closed';
}
currentArg = currentArg + str.substring(i+1, endQuoteIndex);
i = endQuoteIndex;
break;
case '"':
// Double quotes can contain escaped characters
for (i++; i < str.length && str[i] !== '"'; i++) {
if (str[i] === '\\' && (i+1) < str.length) {
i++;
switch (str[i]) {
case 'n':
currentArg += '\n';
break;
case 'r':
currentArg += '\r';
break;
case 't':
currentArg += '\t';
break;
default:
currentArg += str[i];
}
} else {
currentArg += str[i];
}
}
if (i >= str.length) {
throw 'double quote not closed';
}
break;
case ' ':
case '\t':
args.push(currentArg);
currentArg = '';
while (i < str.length && (str[i] === ' ' || str[i] === '\t')) {
i++;
}
// We will have advanced to the next non-whitespace
i--;
break;
case '\\':
i++;
if (i < str.length) {
currentArg = currentArg + str[i];
} else {
throw 'uncompleted escape character';
}
break;
default:
currentArg = currentArg + str[i];
break;
}
}
if (currentArg != '') {
args.push(currentArg);
}
return args;
}
Loading

0 comments on commit 9a1eddc

Please sign in to comment.