Skip to content

Commit

Permalink
feat: basic test
Browse files Browse the repository at this point in the history
  • Loading branch information
johanneswuerbach committed Nov 29, 2022
1 parent 69fc62f commit 4ca155d
Show file tree
Hide file tree
Showing 9 changed files with 6,420 additions and 995 deletions.
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})],
),
);
});
});
103 changes: 103 additions & 0 deletions action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import * as docker from './docker';
import {humanitecFactory} from './humanitec';

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

/**
* Performs the GitHub action.
*/
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 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 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 (!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 != '' && !existsSync(file)) {
core.error(`Cannot find file ${file}`);
core.setFailed('Cannot find file.');
return;
}

if (!existsSync(context)) {
core.error(`Context path does not exist: ${context}`);
core.setFailed('Context path does not exist.');
return;
}

const humanitec = humanitecFactory(token, orgId, apiHost);

let registryCreds;
try {
registryCreds = await humanitec.getRegistryCredentials();
} catch (error) {
core.error('Unable to fetch repository credentials.');
core.error('Did you add the token to your Github Secrets? ' +
'http:/docs.humanitec.com/connecting-your-ci#github-actions');
core.setFailed('Unable to access Humanitec.');
return;
}

if (!docker.login(registryCreds.username, registryCreds.password, registryHost)) {
core.setFailed('Unable to connect to the humanitec registry.');
return;
}

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

let version = '';
if (autoTag && ref.includes('/tags/')) {
version = ref.replace(/.*\/tags\//, '');
} else if (tag) {
version = tag;
} else {
version = commit;
}
const localTag = `${orgId}/${imageName}:${version}`;
const imageId = await docker.build(localTag, file, additionalDockerArguments, context);
if (!imageId) {
core.setFailed('Unable build image from Dockerfile.');
return;
}

const remoteTag = `${registryHost}/${localTag}`;
if (!docker.push(imageId, remoteTag)) {
core.setFailed('Unable to push image to registry');
return;
}

const payload = {
name: `${registryHost}/${orgId}/${imageName}`,
type: 'container',
version,
ref,
commit,
};

try {
await humanitec.addNewVersion(payload);
} catch (error) {
core.error('Unable to notify Humanitec about build.');
core.error('Did you add the token to your Github Secrets? ' +
'http:/docs.humanitec.com/connecting-your-ci#github-actions');
core.setFailed('Unable to access Humanitec.');
return;
}
}
3 changes: 3 additions & 0 deletions fixtures/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM scratch

ENV almost empty
103 changes: 1 addition & 102 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,5 @@
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() {
// 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 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 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 (!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 != '' && !existsSync(file)) {
core.error(`Cannot find file ${file}`);
core.setFailed('Cannot find file.');
return;
}

if (!existsSync(context)) {
core.error(`Context path does not exist: ${context}`);
core.setFailed('Context path does not exist.');
return;
}

const humanitec = humanitecFactory(token, orgId, apiHost);

let registryCreds;
try {
registryCreds = await humanitec.getRegistryCredentials();
} catch (error) {
core.error('Unable to fetch repository credentials.');
core.error('Did you add the token to your Github Secrets? ' +
'http:/docs.humanitec.com/connecting-your-ci#github-actions');
core.setFailed('Unable to access Humanitec.');
return;
}

if (!docker.login(registryCreds.username, registryCreds.password, registryHost)) {
core.setFailed('Unable to connect to the humanitec registry.');
return;
}

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

let version = '';
if (autoTag && ref.includes('/tags/')) {
version = ref.replace(/.*\/tags\//, '');
} else if (tag) {
version = tag;
} else {
version = commit;
}
const localTag = `${orgId}/${imageName}:${version}`;
const imageId = await docker.build(localTag, file, additionalDockerArguments, context);
if (!imageId) {
core.setFailed('Unable build image from Dockerfile.');
return;
}

const remoteTag = `${registryHost}/${localTag}`;
if (!docker.push(imageId, remoteTag)) {
core.setFailed('Unable to push image to registry');
return;
}

const payload = {
name: `${registryHost}/${orgId}/${imageName}`,
type: 'container',
version,
ref,
commit,
};

try {
await humanitec.addNewVersion(payload);
} catch (error) {
core.error('Unable to notify Humanitec about build.');
core.error('Did you add the token to your Github Secrets? ' +
'http:/docs.humanitec.com/connecting-your-ci#github-actions');
core.setFailed('Unable to access Humanitec.');
return;
}
}
import {runAction} from './action';

runAction().catch((e) => {
core.error('Action failed');
Expand Down
6 changes: 6 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testTimeout: 30000,
};
Loading

0 comments on commit 4ca155d

Please sign in to comment.