@adobe/helix-deploy
Version:
Library and Commandline Tools to build and deploy OpenWhisk Actions
182 lines (164 loc) • 5.23 kB
JavaScript
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import path from 'path';
import chalk from 'chalk-template';
import semver from 'semver';
import { h1, context } from '@adobe/fetch';
export default class BaseDeployer {
constructor(cfg) {
this.isDeployer = true;
this.cfg = cfg;
}
get log() {
return this.cfg.log;
}
// eslint-disable-next-line class-methods-use-this
async init() {
// nothing to do
}
ready() {
return this.cfg && false;
}
validate() {
if (!this.ready()) {
throw Error(`${this.name} target not valid.`);
}
}
getOrCreateFetchContext() {
if (!this._fetchContext) {
this._fetchContext = process.env.HELIX_FETCH_FORCE_HTTP1
? h1()
: context();
}
return this._fetchContext;
}
resetFetchContext() {
if (this._fetchContext) {
this._fetchContext.reset();
this._fetchContext = null;
}
}
async close() {
await this.resetFetchContext();
}
get fetch() {
return this.getOrCreateFetchContext().fetch;
}
get relZip() {
return path.relative(process.cwd(), this.cfg.zipFile);
}
get host() {
// note: most derived classes can offer a better implementation,
// this is the lowest common denominator
if (this.cfg.functionURL) {
return new URL(this.cfg.functionURL).hostname;
}
return null;
}
// eslint-disable-next-line class-methods-use-this
get urlVCL() {
return 'req.url';
}
// eslint-disable-next-line class-methods-use-this
get customVCL() {
return '';
}
async testRequest({
url,
headers = {},
idHeader,
retry404 = 0,
}) {
if (this.cfg.testHeaders) {
// eslint-disable-next-line no-param-reassign
headers = Object.assign(headers, this.cfg.testHeaders);
}
while (retry404 >= 0) {
// eslint-disable-next-line no-param-reassign
const testUrl = `${url}${this.cfg.testPath || ''}`;
this.log.info(chalk`--: requesting: {blueBright ${testUrl}} ...`);
// eslint-disable-next-line no-await-in-loop
const ret = await this.fetch(testUrl, {
headers,
cache: 'no-store',
redirect: 'manual',
});
// eslint-disable-next-line no-await-in-loop
const body = await ret.text();
const id = idHeader ? ret.headers.get(idHeader) : 'n/a';
if (ret.ok) {
this.log.info(chalk`id: {grey ${id}}`);
this.log.info(chalk`{green ok:} ${ret.status}`);
this.log.debug(chalk`{grey ${JSON.stringify(ret.headers.plain(), null, 2)}}`);
this.log.debug('');
this.log.debug(chalk`{grey ${body}}`);
return;
}
if (ret.status === 302 || ret.status === 301) {
this.log.info(chalk`{green ok:} ${ret.status}`);
this.log.debug(chalk`{grey Location: ${ret.headers.get('location')}}`);
return;
}
this.log.info(chalk`id: {grey ${id}}`);
if ((ret.status === 404 || ret.status === 500) && retry404) {
this.log.info(chalk`{yellow warn:} ${ret.status} (retry)`);
// eslint-disable-next-line no-param-reassign
retry404 -= 1;
// eslint-disable-next-line no-await-in-loop
await new Promise((resolve) => {
setTimeout(resolve, 1500);
});
} else {
// this.log.info(chalk`{red error:} test failed: ${ret.status} ${body}`);
throw new Error(`test failed: ${ret.status} ${body}`);
}
}
}
/**
* Can be used by deployers to run additional tasks, eg. custom commands.
*/
// eslint-disable-next-line class-methods-use-this,no-empty-function
async runAdditionalTasks() {
}
/**
* Can be used by deployers to validate additional tasks, eg. custom commands.
*/
// eslint-disable-next-line class-methods-use-this,no-empty-function
async validateAdditionalTasks() {
}
/**
* Returns the link versions based on the configuration. eg ['v8', 'ci']
*/
getLinkVersions() {
const sfx = [];
// eslint-disable-next-line no-underscore-dangle
const s = semver.parse(this.cfg.version);
// eslint-disable-next-line no-underscore-dangle
this.cfg.links.forEach((link) => {
if (link === 'major' || link === 'minor') {
if (!s) {
// eslint-disable-next-line no-underscore-dangle
this.log.warn(chalk`{yellow warn:} Ignoring ${link} version link for ${this.cfg.version}. No semver format.`);
return;
}
if (link === 'major') {
sfx.push(`v${s.major}`);
} else {
sfx.push(`v${s.major}.${s.minor}`);
}
} else {
sfx.push(link);
}
});
return sfx;
}
}