@adobe/helix-deploy 13.5.8 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/index.js +1 -0
- package/package.json +13 -16
- package/src/ActionBuilder.js +12 -0
- package/src/BaseConfig.js +1 -1
- package/src/bundler/BaseBundler.js +2 -6
- package/src/cli.js +0 -2
- package/src/deploy/BaseDeployer.js +10 -0
- package/src/deploy/GoogleConfig.js +0 -71
- package/src/deploy/GoogleDeployer.js +0 -352
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## [14.0.1](https://github.com/adobe/helix-deploy/compare/v14.0.0...v14.0.1) (2026-04-21)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **deps:** update external fixes ([#915](https://github.com/adobe/helix-deploy/issues/915)) ([aeb0868](https://github.com/adobe/helix-deploy/commit/aeb0868b6046b71bf4b5436f280bcd1fef55491e))
|
|
7
|
+
|
|
8
|
+
# [14.0.0](https://github.com/adobe/helix-deploy/compare/v13.5.8...v14.0.0) (2026-04-14)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* move google deployer to plugin ([#914](https://github.com/adobe/helix-deploy/issues/914)) ([015a73b](https://github.com/adobe/helix-deploy/commit/015a73b875fd7ab05c7c83402ba62be6c0d42649))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### BREAKING CHANGES
|
|
17
|
+
|
|
18
|
+
* deploying to GCF will require an additional --plugin argument
|
|
19
|
+
|
|
1
20
|
## [13.5.8](https://github.com/adobe/helix-deploy/compare/v13.5.7...v13.5.8) (2026-04-13)
|
|
2
21
|
|
|
3
22
|
|
package/index.js
CHANGED
|
@@ -14,3 +14,4 @@ export { default as BaseBundler } from './src/bundler/BaseBundler.js';
|
|
|
14
14
|
export { default as BaseConfig } from './src/BaseConfig.js';
|
|
15
15
|
export { default as BaseDeployer } from './src/deploy/BaseDeployer.js';
|
|
16
16
|
export { default as CLI } from './src/cli.js';
|
|
17
|
+
export { filterActions } from './src/utils.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/helix-deploy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.0.1",
|
|
4
4
|
"description": "Library and Commandline Tools to build and deploy OpenWhisk Actions",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/adobe/helix-deploy#readme",
|
|
@@ -39,22 +39,19 @@
|
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@adobe/fetch": "4.3.0",
|
|
41
41
|
"@adobe/helix-shared-process-queue": "3.1.8",
|
|
42
|
-
"@aws-sdk/client-apigatewayv2": "3.
|
|
43
|
-
"@aws-sdk/client-lambda": "3.
|
|
44
|
-
"@aws-sdk/client-s3": "3.
|
|
45
|
-
"@aws-sdk/client-secrets-manager": "3.
|
|
46
|
-
"@aws-sdk/client-ssm": "3.
|
|
47
|
-
"@aws-sdk/client-sts": "3.
|
|
48
|
-
"@google-cloud/functions": "4.2.1",
|
|
49
|
-
"@google-cloud/secret-manager": "6.1.1",
|
|
50
|
-
"@google-cloud/storage": "7.19.0",
|
|
42
|
+
"@aws-sdk/client-apigatewayv2": "3.1025.0",
|
|
43
|
+
"@aws-sdk/client-lambda": "3.1025.0",
|
|
44
|
+
"@aws-sdk/client-s3": "3.1025.0",
|
|
45
|
+
"@aws-sdk/client-secrets-manager": "3.1025.0",
|
|
46
|
+
"@aws-sdk/client-ssm": "3.1025.0",
|
|
47
|
+
"@aws-sdk/client-sts": "3.1025.0",
|
|
51
48
|
"archiver": "7.0.1",
|
|
52
49
|
"chalk-template": "1.1.2",
|
|
53
|
-
"dotenv": "17.
|
|
54
|
-
"esbuild": "0.
|
|
50
|
+
"dotenv": "17.4.1",
|
|
51
|
+
"esbuild": "0.28.0",
|
|
55
52
|
"escalade": "3.2.0",
|
|
56
53
|
"fs-extra": "11.3.4",
|
|
57
|
-
"isomorphic-git": "1.37.
|
|
54
|
+
"isomorphic-git": "1.37.5",
|
|
58
55
|
"openwhisk": "3.21.8",
|
|
59
56
|
"semver": "7.7.4",
|
|
60
57
|
"yargs": "18.0.0"
|
|
@@ -63,7 +60,7 @@
|
|
|
63
60
|
"@adobe/eslint-config-helix": "3.0.24",
|
|
64
61
|
"@adobe/helix-shared-wrap": "2.0.2",
|
|
65
62
|
"@adobe/helix-status": "10.1.5",
|
|
66
|
-
"@eslint/config-helpers": "0.5.
|
|
63
|
+
"@eslint/config-helpers": "0.5.4",
|
|
67
64
|
"@semantic-release/changelog": "6.0.3",
|
|
68
65
|
"@semantic-release/git": "10.0.1",
|
|
69
66
|
"c8": "11.0.0",
|
|
@@ -73,10 +70,10 @@
|
|
|
73
70
|
"mocha": "11.7.5",
|
|
74
71
|
"mocha-junit-reporter": "2.2.1",
|
|
75
72
|
"mocha-multi-reporters": "1.5.1",
|
|
76
|
-
"nock": "14.0.
|
|
73
|
+
"nock": "14.0.12",
|
|
77
74
|
"semantic-release": "25.0.3",
|
|
78
75
|
"xml2js": "0.6.2",
|
|
79
|
-
"yauzl": "3.
|
|
76
|
+
"yauzl": "3.3.0"
|
|
80
77
|
},
|
|
81
78
|
"engines": {
|
|
82
79
|
"node": ">=18.0"
|
package/src/ActionBuilder.js
CHANGED
|
@@ -290,6 +290,18 @@ export default class ActionBuilder {
|
|
|
290
290
|
}
|
|
291
291
|
this.bundlers.push(...bundler);
|
|
292
292
|
});
|
|
293
|
+
|
|
294
|
+
// collect archive dependencies from all registered deployers and inject into bundlers
|
|
295
|
+
const archiveDependencies = Object.values(this._deployers).reduce((deps, deployer) => {
|
|
296
|
+
if (typeof deployer.getArchiveDependencies === 'function') {
|
|
297
|
+
Object.assign(deps, deployer.getArchiveDependencies());
|
|
298
|
+
}
|
|
299
|
+
return deps;
|
|
300
|
+
}, {});
|
|
301
|
+
for (const bundler of this.bundlers) {
|
|
302
|
+
bundler.archiveDependencies = archiveDependencies;
|
|
303
|
+
}
|
|
304
|
+
|
|
293
305
|
for (const bundler of this.bundlers) {
|
|
294
306
|
await bundler.init();
|
|
295
307
|
}
|
package/src/BaseConfig.js
CHANGED
|
@@ -707,7 +707,7 @@ export default class BaseConfig {
|
|
|
707
707
|
|
|
708
708
|
.group(['target', 'hints'], 'Deploy Options')
|
|
709
709
|
.option('target', {
|
|
710
|
-
description: 'Select target(s) for test, deploy, update-package actions (wsk,aws,
|
|
710
|
+
description: 'Select target(s) for test, deploy, update-package actions (wsk,aws,auto) or plugin targets (e.g. google via @adobe/helix-deploy-plugin-google)',
|
|
711
711
|
type: 'string',
|
|
712
712
|
default: ['auto'],
|
|
713
713
|
array: true,
|
|
@@ -16,7 +16,6 @@ import chalk from 'chalk-template';
|
|
|
16
16
|
import archiver from 'archiver';
|
|
17
17
|
import semver from 'semver';
|
|
18
18
|
import { validateBundle } from '../utils.js';
|
|
19
|
-
import pkgJson from '../package.cjs';
|
|
20
19
|
|
|
21
20
|
// eslint-disable-next-line no-underscore-dangle
|
|
22
21
|
const __dirname = path.resolve(fileURLToPath(import.meta.url), '..');
|
|
@@ -43,6 +42,7 @@ export default class BaseBundler {
|
|
|
43
42
|
cfg,
|
|
44
43
|
arch: '',
|
|
45
44
|
type: '',
|
|
45
|
+
archiveDependencies: {},
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
|
|
@@ -113,11 +113,7 @@ export default class BaseBundler {
|
|
|
113
113
|
type: cfg.esm ? 'module' : 'script',
|
|
114
114
|
license: 'Apache-2.0',
|
|
115
115
|
dependencies: {
|
|
116
|
-
|
|
117
|
-
// all other environments ignore them – this allows us to
|
|
118
|
-
// avoid bundling something that only google needs
|
|
119
|
-
'@google-cloud/secret-manager': pkgJson.dependencies['@google-cloud/secret-manager'],
|
|
120
|
-
'@google-cloud/storage': pkgJson.dependencies['@google-cloud/storage'],
|
|
116
|
+
...this.archiveDependencies,
|
|
121
117
|
},
|
|
122
118
|
};
|
|
123
119
|
archive.pipe(output);
|
package/src/cli.js
CHANGED
|
@@ -19,14 +19,12 @@ import escalade from 'escalade/sync';
|
|
|
19
19
|
import BaseConfig from './BaseConfig.js';
|
|
20
20
|
import OpenWhiskDeployer from './deploy/OpenWhiskDeployer.js';
|
|
21
21
|
import AWSDeployer from './deploy/AWSDeployer.js';
|
|
22
|
-
import GoogleDeployer from './deploy/GoogleDeployer.js';
|
|
23
22
|
import ActionBuilder from './ActionBuilder.js';
|
|
24
23
|
import ESBuildBundler from './bundler/ESBuildBundler.js';
|
|
25
24
|
|
|
26
25
|
const PLUGINS = [
|
|
27
26
|
OpenWhiskDeployer,
|
|
28
27
|
AWSDeployer,
|
|
29
|
-
GoogleDeployer,
|
|
30
28
|
ESBuildBundler,
|
|
31
29
|
];
|
|
32
30
|
|
|
@@ -138,6 +138,16 @@ export default class BaseDeployer {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Returns additional dependencies to include in the archive's package.json.
|
|
143
|
+
* Deployers can override this to inject runtime dependencies needed by the target platform.
|
|
144
|
+
* @returns {object} an object mapping package names to version strings
|
|
145
|
+
*/
|
|
146
|
+
// eslint-disable-next-line class-methods-use-this
|
|
147
|
+
getArchiveDependencies() {
|
|
148
|
+
return {};
|
|
149
|
+
}
|
|
150
|
+
|
|
141
151
|
/**
|
|
142
152
|
* Can be used by deployers to run additional tasks, eg. custom commands.
|
|
143
153
|
*/
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
export default class GoogleConfig {
|
|
13
|
-
constructor() {
|
|
14
|
-
Object.assign(this, {
|
|
15
|
-
appName: '',
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
configure(argv) {
|
|
20
|
-
return this
|
|
21
|
-
.withProjectID(argv.googleProjectId)
|
|
22
|
-
.withKeyFile(argv.googleKeyFile)
|
|
23
|
-
.withRegion(argv.googleRegion)
|
|
24
|
-
.withEmail(argv.googleEmail);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
withProjectID(value) {
|
|
28
|
-
this.projectID = value;
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
withKeyFile(value) {
|
|
33
|
-
this.keyFile = value;
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
withEmail(value) {
|
|
38
|
-
this.email = value;
|
|
39
|
-
return this;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
withRegion(value) {
|
|
43
|
-
this.region = value;
|
|
44
|
-
return this;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
static yarg(yargs) {
|
|
48
|
-
return yargs
|
|
49
|
-
.group(['google-project-id', 'google-key-file', 'google-email'], 'Google Deployment Options')
|
|
50
|
-
.option('google-email', {
|
|
51
|
-
description: 'the Google account email address. Required when using a .pem or .p12 credential file',
|
|
52
|
-
type: 'string',
|
|
53
|
-
default: '',
|
|
54
|
-
})
|
|
55
|
-
.option('google-key-file', {
|
|
56
|
-
description: 'full path to the a .json, .pem, or .p12 key downloaded from the Google Developers Console',
|
|
57
|
-
type: 'string',
|
|
58
|
-
default: '',
|
|
59
|
-
})
|
|
60
|
-
.option('google-project-id', {
|
|
61
|
-
description: 'the Google Cloud project to deploy to. Optional when the key file is a JSON file',
|
|
62
|
-
type: 'string',
|
|
63
|
-
default: '',
|
|
64
|
-
})
|
|
65
|
-
.option('google-region', {
|
|
66
|
-
description: 'the Google Cloud region to deploy in',
|
|
67
|
-
type: 'string',
|
|
68
|
-
default: '',
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright 2021 Adobe. All rights reserved.
|
|
3
|
-
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
-
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
-
*
|
|
7
|
-
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
-
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
-
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
-
* governing permissions and limitations under the License.
|
|
11
|
-
*/
|
|
12
|
-
import { CloudFunctionsServiceClient } from '@google-cloud/functions';
|
|
13
|
-
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
|
|
14
|
-
import path from 'path';
|
|
15
|
-
import fs from 'fs';
|
|
16
|
-
import semver from 'semver';
|
|
17
|
-
import chalk from 'chalk-template';
|
|
18
|
-
import BaseDeployer from './BaseDeployer.js';
|
|
19
|
-
import GoogleConfig from './GoogleConfig.js';
|
|
20
|
-
import { filterActions } from '../utils.js';
|
|
21
|
-
|
|
22
|
-
export default class GoogleDeployer extends BaseDeployer {
|
|
23
|
-
constructor(baseConfig, config) {
|
|
24
|
-
super(baseConfig);
|
|
25
|
-
Object.assign(this, {
|
|
26
|
-
id: 'google',
|
|
27
|
-
name: 'Google',
|
|
28
|
-
_cfg: config,
|
|
29
|
-
_client: null,
|
|
30
|
-
_keyFilename: '',
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
ready() {
|
|
35
|
-
if (this._cfg.keyFile) {
|
|
36
|
-
this._keyFilename = path.resolve(process.cwd(), this._cfg.keyFile);
|
|
37
|
-
if (!fs.existsSync(this._keyFilename)) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return !!this._cfg.projectID && !!this._cfg.keyFile;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
validate() {
|
|
45
|
-
if (!this.ready()) {
|
|
46
|
-
throw new Error('Google target needs key file, email, and project ID');
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async init() {
|
|
51
|
-
if (this.ready() && !this._client) {
|
|
52
|
-
try {
|
|
53
|
-
this._client = new CloudFunctionsServiceClient({
|
|
54
|
-
email: this._cfg.email,
|
|
55
|
-
keyFilename: this._keyFilename,
|
|
56
|
-
projectId: this._cfg.projectID,
|
|
57
|
-
});
|
|
58
|
-
this._secretclient = new SecretManagerServiceClient({
|
|
59
|
-
email: this._cfg.email,
|
|
60
|
-
keyFilename: this._keyFilename,
|
|
61
|
-
projectId: this._cfg.projectID,
|
|
62
|
-
});
|
|
63
|
-
} catch (e) {
|
|
64
|
-
this.log.error(chalk`{red error:} Unable to authenticate with Google: ${e.message}`);
|
|
65
|
-
throw e;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async updatePackage() {
|
|
71
|
-
this.log.info('--: updating app (package) parameters ...');
|
|
72
|
-
// Create the secret with automation replication.
|
|
73
|
-
const secretId = `helix-deploy--${this.cfg.packageName.replace(/\./g, '_')}`;
|
|
74
|
-
const parent = `projects/${this._cfg.projectID}`;
|
|
75
|
-
let secret;
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
[secret] = await this._secretclient.createSecret({
|
|
79
|
-
parent,
|
|
80
|
-
secret: {
|
|
81
|
-
name: secretId,
|
|
82
|
-
replication: {
|
|
83
|
-
automatic: {},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
secretId,
|
|
87
|
-
});
|
|
88
|
-
this.log.info(`--: Created secret ${secret.name}`);
|
|
89
|
-
} catch {
|
|
90
|
-
this.log.info('--: Using existing secret');
|
|
91
|
-
[secret] = await this._secretclient.getSecret({
|
|
92
|
-
name: `${parent}/secrets/${secretId}`,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Add a version with a payload onto the secret.
|
|
97
|
-
const [version] = await this._secretclient.addSecretVersion({
|
|
98
|
-
parent: secret.name,
|
|
99
|
-
payload: {
|
|
100
|
-
data: Buffer.from(JSON.stringify(this.cfg.packageParams), 'utf8'),
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
this.log.info(chalk`{green ok}: Added secret version ${version.name}`);
|
|
105
|
-
|
|
106
|
-
/*
|
|
107
|
-
const [retversion] = await this._secretclient.accessSecretVersion({
|
|
108
|
-
name: `${parent}/secrets/${secretId}/versions/latest`,
|
|
109
|
-
});
|
|
110
|
-
const payload = JSON.parse(retversion.payload.data.toString());
|
|
111
|
-
|
|
112
|
-
this.log.info(payload);
|
|
113
|
-
*/
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
async uploadZIP() {
|
|
117
|
-
const [{ uploadUrl }] = await this._client.generateUploadUrl({
|
|
118
|
-
parent: `projects/${this._cfg.projectID}/locations/${this._cfg.region}`,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const body = fs.createReadStream(this.cfg.zipFile);
|
|
122
|
-
|
|
123
|
-
// upload
|
|
124
|
-
await this.fetch(uploadUrl, {
|
|
125
|
-
method: 'PUT',
|
|
126
|
-
headers: {
|
|
127
|
-
'Content-Type': 'application/zip',
|
|
128
|
-
'x-goog-content-length-range': '0,104857600',
|
|
129
|
-
},
|
|
130
|
-
body,
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
this._uploadURL = uploadUrl;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
get fullFunctionName() {
|
|
137
|
-
return `${this.cfg.packageName}--${this.cfg.name}`
|
|
138
|
-
.replace(/\./g, '_')
|
|
139
|
-
.replace('@', '_');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async createFunction() {
|
|
143
|
-
const name = `projects/${this._cfg.projectID}/locations/${this._cfg.region}/functions/${this.fullFunctionName}`;
|
|
144
|
-
let exists = false;
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
await this._client.getFunction({
|
|
148
|
-
name,
|
|
149
|
-
});
|
|
150
|
-
exists = true;
|
|
151
|
-
} catch {
|
|
152
|
-
exists = false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
try {
|
|
156
|
-
const func = {
|
|
157
|
-
name,
|
|
158
|
-
serviceAccountEmail: this._cfg.email,
|
|
159
|
-
description: this.cfg.pkgJson.description,
|
|
160
|
-
entryPoint: 'google',
|
|
161
|
-
runtime: `nodejs${this.cfg.nodeVersion}`,
|
|
162
|
-
// timeout: `${Math.floor(this.cfg.timeout / 1000)}s`,
|
|
163
|
-
availableMemoryMb: this.cfg.memory,
|
|
164
|
-
labels: {
|
|
165
|
-
/*
|
|
166
|
-
* Each resource can have multiple labels, up to a maximum of 64.
|
|
167
|
-
* - Each label must be a key-value pair.
|
|
168
|
-
* - Keys have a minimum length of 1 character and a maximum length of 63
|
|
169
|
-
* characters, and cannot be empty. Values can be empty, and have a maximum
|
|
170
|
-
* length of 63 characters.
|
|
171
|
-
* - Keys and values can contain only lowercase letters, numeric characters,
|
|
172
|
-
* underscores, and dashes. All characters must use UTF-8 encoding, and
|
|
173
|
-
* international characters are allowed.
|
|
174
|
-
* - The key portion of a label must be unique. However, you can use the same key
|
|
175
|
-
* with multiple resources.
|
|
176
|
-
* - Keys must start with a lowercase letter or international character.
|
|
177
|
-
*/
|
|
178
|
-
// not worth the effort, I think
|
|
179
|
-
pkgversion: `${encodeURIComponent(this.cfg.version.replace(/\./g, '_'))}`,
|
|
180
|
-
// dependencies: this.cfg.dependencies.main
|
|
181
|
-
// .map((dep) => `${dep.name}:${dep.version}`).join(','),
|
|
182
|
-
// repository: encodeURIComponent(this.cfg.gitUrl).replace(/%/g, '_'),
|
|
183
|
-
// git: `${this.cfg.gitOrigin}#${this.cfg.gitRef}`,
|
|
184
|
-
updated: `${this.cfg.updatedAt}`,
|
|
185
|
-
},
|
|
186
|
-
environmentVariables: this.cfg.params,
|
|
187
|
-
httpsTrigger: {},
|
|
188
|
-
sourceUploadUrl: this._uploadURL,
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
if (exists) {
|
|
192
|
-
const [op] = await this._client.updateFunction({
|
|
193
|
-
// location: `projects/${this._cfg.projectID}/locations/${this._cfg.region}`,
|
|
194
|
-
function: func,
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
this.log.info('--: updating existing function');
|
|
198
|
-
const [res] = await op.promise();
|
|
199
|
-
this._function = res;
|
|
200
|
-
this.log.info(chalk`{green ok:} function deployed`);
|
|
201
|
-
} else {
|
|
202
|
-
const [op] = await this._client.createFunction({
|
|
203
|
-
location: `projects/${this._cfg.projectID}/locations/${this._cfg.region}`,
|
|
204
|
-
function: func,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
this.log.info('--: creating function, please wait (Google deployments are slow).');
|
|
208
|
-
const [res] = await op.promise();
|
|
209
|
-
this._function = res;
|
|
210
|
-
this.log.info(chalk`{green ok:} function deployed`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
this.log.info('--: enabling unauthenticated requests');
|
|
214
|
-
await this._client.setIamPolicy({
|
|
215
|
-
resource: name,
|
|
216
|
-
policy: {
|
|
217
|
-
bindings: [
|
|
218
|
-
{
|
|
219
|
-
role: 'roles/cloudfunctions.invoker',
|
|
220
|
-
members: [
|
|
221
|
-
'allUsers',
|
|
222
|
-
],
|
|
223
|
-
},
|
|
224
|
-
],
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
} catch (err) {
|
|
228
|
-
this.log.error(chalk`{red error:} bad request: ${err.metadata.internalRepr?.get('google.rpc.badrequest-bin')?.toString()}`);
|
|
229
|
-
this.log.error(chalk`{red error:} details: ${err.metadata.internalRepr?.get('grpc-status-details-bin')?.toString()}`);
|
|
230
|
-
throw err;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
this._functionURL = this._function.httpsTrigger.url;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
async deploy() {
|
|
237
|
-
try {
|
|
238
|
-
await this.uploadZIP();
|
|
239
|
-
await this.createFunction();
|
|
240
|
-
} catch (err) {
|
|
241
|
-
const message = err.metadata ? err.metadata.get('grpc-status-details-bin')[0].toString() : err.message;
|
|
242
|
-
this.log.error(chalk`{red error:} Unable to deploy Google Cloud function: ${message}`, err.metadata);
|
|
243
|
-
throw err;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
get host() {
|
|
248
|
-
return `${this._cfg.region}-${this._cfg.projectID}.cloudfunctions.net`;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// eslint-disable-next-line class-methods-use-this
|
|
252
|
-
get urlVCL() {
|
|
253
|
-
return '"/" + var.package + "--" + var.action + regsuball(var._version, "\\.", "_") + var.rest';
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
get basePath() {
|
|
257
|
-
return `/${this.fullFunctionName}`;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
async test() {
|
|
261
|
-
let url = this._functionURL;
|
|
262
|
-
if (!url) {
|
|
263
|
-
url = `https://${this._cfg.region}-${this._cfg.projectID}.cloudfunctions.net/${this.fullFunctionName}`;
|
|
264
|
-
}
|
|
265
|
-
return this.testRequest({
|
|
266
|
-
url,
|
|
267
|
-
idHeader: 'X-Cloud-Trace-Context',
|
|
268
|
-
retry404: 1,
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
async cleanup() {
|
|
273
|
-
if (!this._client) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
const [allfns] = await this._client.listFunctions({
|
|
279
|
-
parent: `projects/${this._cfg.projectID}/locations/${this._cfg.region}`,
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
const versionspec = {};
|
|
283
|
-
const sver = semver.parse(this.cfg.version);
|
|
284
|
-
if (sver) {
|
|
285
|
-
versionspec.patchVersion = sver.patch;
|
|
286
|
-
versionspec.minorVersion = sver.minor;
|
|
287
|
-
versionspec.majorVersion = sver.major;
|
|
288
|
-
}
|
|
289
|
-
await Promise.all(GoogleDeployer.filterFunctions(
|
|
290
|
-
allfns,
|
|
291
|
-
this.cfg.baseName,
|
|
292
|
-
Date.now(),
|
|
293
|
-
{
|
|
294
|
-
ciAge: this.cfg.cleanupCiAge,
|
|
295
|
-
patchAge: this.cfg.cleanupPatchAge,
|
|
296
|
-
minorAge: this.cfg.cleanupMinorAge,
|
|
297
|
-
majorAge: this.cfg.cleanupMajorAge,
|
|
298
|
-
ciNum: this.cfg.cleanupCiNum,
|
|
299
|
-
patchNum: this.cfg.cleanupPatchNum,
|
|
300
|
-
minorNum: this.cfg.cleanupMinorNum,
|
|
301
|
-
majorNum: this.cfg.cleanupMajorNum,
|
|
302
|
-
},
|
|
303
|
-
versionspec,
|
|
304
|
-
).map((fn) => {
|
|
305
|
-
this.log.info(`--: Cleaning up outdated function '${fn.fqName}`);
|
|
306
|
-
|
|
307
|
-
return this._client.deleteFunction({
|
|
308
|
-
name: fn.fqName,
|
|
309
|
-
});
|
|
310
|
-
}));
|
|
311
|
-
} catch (e) {
|
|
312
|
-
this.log.error(chalk`{red error:} Cleanup failed, proceeding anyway.`, e);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
static filterFunctions(fns, name, now, rangespec, versionspec) {
|
|
317
|
-
const namedfns = fns.map((fn) => {
|
|
318
|
-
const re = /(ci\d+)|(\d+_\d+_\d+)$/;
|
|
319
|
-
|
|
320
|
-
const updated = fn.labels && fn.labels.updated
|
|
321
|
-
? fn.labels.updated
|
|
322
|
-
: fn.updateTime.seconds;
|
|
323
|
-
|
|
324
|
-
const versionstr = fn.labels && fn.labels.pkgversion
|
|
325
|
-
? fn.labels.pkgversion
|
|
326
|
-
: fn.name.match(re) && fn.name.match(re)[0];
|
|
327
|
-
|
|
328
|
-
const version = {};
|
|
329
|
-
if (versionstr && versionstr.startsWith('ci')) {
|
|
330
|
-
version.ci = versionstr.substr(2);
|
|
331
|
-
} else if (versionstr) {
|
|
332
|
-
const cleanversionstr = versionstr
|
|
333
|
-
.replace(/^(\d+)[-_](\d+)[-_](\d+)[-_]/, '$1.$2.$3-')
|
|
334
|
-
.replace(/^(\d+)[-_](\d+)[-_](\d+)/, '$1.$2.$3');
|
|
335
|
-
const ver = semver.parse(cleanversionstr);
|
|
336
|
-
version.major = ver.major;
|
|
337
|
-
version.minor = ver.minor;
|
|
338
|
-
version.patch = ver.patch;
|
|
339
|
-
}
|
|
340
|
-
return {
|
|
341
|
-
fqName: fn.name,
|
|
342
|
-
name: fn.name.replace(/^.*--/, '').replace(re, '').replace(/_$/, ''),
|
|
343
|
-
updated: new Date(Number(updated)),
|
|
344
|
-
version,
|
|
345
|
-
};
|
|
346
|
-
}).filter((fn) => fn.name === name);
|
|
347
|
-
|
|
348
|
-
return filterActions(namedfns, now, rangespec, versionspec);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
GoogleDeployer.Config = GoogleConfig;
|