hammerkit 1.27.0-next.6 → 1.27.0-next.8
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/dist/cache/backends/registry-cache-backend.js +2 -2
- package/dist/kubernetes/ensure-kubernetes-persistent-volume-claim-exists.js +1 -1
- package/dist/kubernetes/ensure-persistent-data.js +8 -8
- package/dist/planner/work-runtime-docker.js +2 -1
- package/dist/planner/work-runtime-local.js +2 -1
- package/dist/server/kubernetes-sandbox-storage.js +2 -1
- package/dist/server/oauth.js +12 -1
- package/dist/server/sandboxes-api.js +10 -4
- package/dist/utils/tar.js +9 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ const crypto_1 = require("crypto");
|
|
|
5
5
|
const os_1 = require("os");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const tar_1 = require("tar");
|
|
8
|
+
const tar_2 = require("../../utils/tar");
|
|
8
9
|
const registry_reference_1 = require("./registry/registry-reference");
|
|
9
10
|
const registry_client_1 = require("./registry/registry-client");
|
|
10
11
|
const MAX_TAG_LENGTH = 128;
|
|
@@ -74,8 +75,7 @@ function createRegistryCacheBackend(spec) {
|
|
|
74
75
|
const layerFile = (0, path_1.join)(dir, 'layer.tar');
|
|
75
76
|
const files = (await environment.file.listFiles(from)).sort();
|
|
76
77
|
// portable + mtime-free so identical entries produce identical digests
|
|
77
|
-
|
|
78
|
-
await (0, tar_1.create)({ file: layerFile, cwd: from, portable: true, noMtime: true }, files);
|
|
78
|
+
await (0, tar_2.packArchive)({ file: layerFile, cwd: from, portable: true, noMtime: true }, files);
|
|
79
79
|
const layer = await (0, registry_client_1.digestFile)(layerFile);
|
|
80
80
|
const config = Buffer.from(JSON.stringify({
|
|
81
81
|
architecture: 'amd64',
|
|
@@ -65,7 +65,7 @@ async function ensureKubernetesPersistentVolumeClaimExists(instance, env, volume
|
|
|
65
65
|
},
|
|
66
66
|
},
|
|
67
67
|
};
|
|
68
|
-
service.status.
|
|
68
|
+
service.status.write('debug', `ensure volume ${volume.name}`);
|
|
69
69
|
// Don't block on the PVC reaching "Bound". Storage classes with
|
|
70
70
|
// volumeBindingMode WaitForFirstConsumer (docker-desktop's "standard",
|
|
71
71
|
// k3d/k3s local-path, most cloud defaults) keep the claim Pending until a pod
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ensurePersistentData = exports.packSource = exports.clearClaim = exports.getPodForPersistence = void 0;
|
|
4
4
|
const apply_1 = require("./apply");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
-
const tar_1 = require("tar");
|
|
6
|
+
const tar_1 = require("../utils/tar");
|
|
7
7
|
const resources_1 = require("./resources");
|
|
8
8
|
const await_running_state_1 = require("./await-running-state");
|
|
9
9
|
const sleep_1 = require("../utils/sleep");
|
|
@@ -104,18 +104,18 @@ async function getPodForPersistence(instance, env, service, persistence, type, f
|
|
|
104
104
|
volumes: persistence.volumes,
|
|
105
105
|
},
|
|
106
106
|
};
|
|
107
|
-
service.status.
|
|
107
|
+
service.status.write('debug', `create pod ${name}`);
|
|
108
108
|
await removeStalePod(instance, env.namespace, name);
|
|
109
109
|
const pod = await (0, apply_1.apply)(instance, podSpec);
|
|
110
110
|
if (pod.status?.phase !== 'Running') {
|
|
111
|
-
service.status.
|
|
111
|
+
service.status.write('debug', `await running state ${name}`);
|
|
112
112
|
await (0, await_running_state_1.awaitRunningState)(instance, env, name, 'Running');
|
|
113
113
|
}
|
|
114
114
|
try {
|
|
115
115
|
await fn(name);
|
|
116
116
|
}
|
|
117
117
|
finally {
|
|
118
|
-
service.status.
|
|
118
|
+
service.status.write('debug', `delete pod ${name}`);
|
|
119
119
|
await instance.coreApi.deleteNamespacedPod({ name, namespace: env.namespace });
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -124,7 +124,7 @@ exports.getPodForPersistence = getPodForPersistence;
|
|
|
124
124
|
// the task runs on it or outputs are restored into it, so it holds what a new one would
|
|
125
125
|
async function clearClaim(instance, env, work, pod) {
|
|
126
126
|
const targetPath = `/dev/hammerkit/${work.id()}`;
|
|
127
|
-
work.status.
|
|
127
|
+
work.status.write('info', `clear what an earlier run left in ${targetPath}`);
|
|
128
128
|
let failure = null;
|
|
129
129
|
const res = await instance.exec.exec(env.namespace, pod, 'volume', ['find', targetPath, '-mindepth', '1', '-maxdepth', '1', '-exec', 'rm', '-rf', '{}', '+'], process.stdout, process.stderr, null, false, (status) => {
|
|
130
130
|
if (status.status !== 'Success') {
|
|
@@ -141,7 +141,7 @@ exports.clearClaim = clearClaim;
|
|
|
141
141
|
// the claim (see getClaimSubPath) instead of under its own name
|
|
142
142
|
function packSource(source) {
|
|
143
143
|
const fileItem = (0, path_1.basename)(source.localPath);
|
|
144
|
-
return stream_1.Readable.from((0, tar_1.
|
|
144
|
+
return stream_1.Readable.from((0, tar_1.packArchive)({
|
|
145
145
|
cwd: (0, path_1.dirname)(source.localPath),
|
|
146
146
|
filter(path) {
|
|
147
147
|
return source.matcher(path, source.localPath);
|
|
@@ -172,7 +172,7 @@ options = {}) {
|
|
|
172
172
|
if (persistence.sources.length === 0 && !options.reset) {
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
|
-
service.status.
|
|
175
|
+
service.status.write('debug', 'start upload container');
|
|
176
176
|
await getPodForPersistence(instance, env, service, persistence, 'write', async (name) => {
|
|
177
177
|
if (options.reset) {
|
|
178
178
|
await clearClaim(instance, env, service, name);
|
|
@@ -183,7 +183,7 @@ options = {}) {
|
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
185
|
const data = packSource(source);
|
|
186
|
-
service.status.
|
|
186
|
+
service.status.write('info', `upload ${source.localPath}`);
|
|
187
187
|
const targetPath = `/dev/hammerkit/${service.id()}`;
|
|
188
188
|
const res = await instance.exec.exec(env.namespace, name, 'volume', ['tar', 'xf', '-', '-C', targetPath], process.stdout, process.stderr, data, false, (status) => {
|
|
189
189
|
service.status.write('debug', `upload ${source.localPath} to ${name}: ${status}`);
|
|
@@ -12,6 +12,7 @@ const event_cache_1 = require("../executer/event-cache");
|
|
|
12
12
|
const get_docker_executor_1 = require("../executer/get-docker-executor");
|
|
13
13
|
const path_1 = require("path");
|
|
14
14
|
const tar_1 = require("tar");
|
|
15
|
+
const tar_2 = require("../utils/tar");
|
|
15
16
|
const plan_work_volume_1 = require("./utils/plan-work-volume");
|
|
16
17
|
const work_instance_id_1 = require("./work-instance-id");
|
|
17
18
|
const stream_1 = require("stream");
|
|
@@ -302,7 +303,7 @@ async function archiveContainer(docker, environment, item, path) {
|
|
|
302
303
|
for (const generatedArchive of (0, event_cache_1.getArchivePaths)(item.data, path)) {
|
|
303
304
|
// a file output is a bind mount of a host file, so archive it from the host
|
|
304
305
|
const readable = hostFiles.has(generatedArchive.path)
|
|
305
|
-
? stream_1.Readable.from((0,
|
|
306
|
+
? stream_1.Readable.from((0, tar_2.packArchive)({ cwd: (0, path_1.dirname)(generatedArchive.path) }, [(0, path_1.basename)(generatedArchive.path)]))
|
|
306
307
|
: await container.getArchive({
|
|
307
308
|
path: generatedArchive.path,
|
|
308
309
|
});
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getLocalWorkRuntime = exports.getStateFilename = void 0;
|
|
7
7
|
const tar_1 = require("tar");
|
|
8
|
+
const tar_2 = require("../utils/tar");
|
|
8
9
|
const path_1 = require("path");
|
|
9
10
|
const local_task_1 = require("../executer/local-task");
|
|
10
11
|
const event_cache_1 = require("../executer/event-cache");
|
|
@@ -121,7 +122,7 @@ async function archiveLocal(environment, task, path) {
|
|
|
121
122
|
for (const generatedArchive of (0, event_cache_1.getArchivePaths)(task.data, path)) {
|
|
122
123
|
await environment.file.writeStream(generatedArchive.filename,
|
|
123
124
|
// tar's stream is a Minipass stream; Readable.from adapts it to a Node one
|
|
124
|
-
stream_1.Readable.from((0,
|
|
125
|
+
stream_1.Readable.from((0, tar_2.packArchive)({ cwd: task.data.cwd, gzip: true }, [(0, path_1.relative)(task.data.cwd, generatedArchive.path)])));
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
async function restoreLocal(environment, task, path) {
|
|
@@ -7,6 +7,7 @@ const path_1 = require("path");
|
|
|
7
7
|
const stream_1 = require("stream");
|
|
8
8
|
const promises_2 = require("stream/promises");
|
|
9
9
|
const tar_1 = require("tar");
|
|
10
|
+
const tar_2 = require("../utils/tar");
|
|
10
11
|
const apply_1 = require("../kubernetes/apply");
|
|
11
12
|
const kubernetes_instance_1 = require("../kubernetes/kubernetes-instance");
|
|
12
13
|
const network_policy_1 = require("../kubernetes/network-policy");
|
|
@@ -463,7 +464,7 @@ class KubernetesSandboxStorage {
|
|
|
463
464
|
await (0, git_checkout_1.git)([`--git-dir=${repository}`, 'fetch', '--quiet', '--depth', '1', '--', fetch.url, fetch.ref], fetch.env, fetch.signal, what);
|
|
464
465
|
await (0, git_checkout_1.git)([`--git-dir=${repository}`, 'update-ref', `refs/heads/${sandbox_pod_1.INCOMING_REF}`, 'FETCH_HEAD'], fetch.env, fetch.signal, what, op);
|
|
465
466
|
const incoming = `${CLAIM_PATH}/${sandbox_pod_1.INCOMING}`;
|
|
466
|
-
await this.withPod(key, (pod) => this.exec(pod, ['sh', '-c', 'rm -rf "$1" && mkdir -p "$1" && tar xf - -C "$1"', 'sh', incoming], stream_1.Readable.from((0,
|
|
467
|
+
await this.withPod(key, (pod) => this.exec(pod, ['sh', '-c', 'rm -rf "$1" && mkdir -p "$1" && tar xf - -C "$1"', 'sh', incoming], stream_1.Readable.from((0, tar_2.packArchive)({ cwd: repository, portable: true }, ['.'])), null, fetch.signal));
|
|
467
468
|
return (await this.request(key, { op, id: key.id }, fetch.signal)).result;
|
|
468
469
|
}
|
|
469
470
|
finally {
|
package/dist/server/oauth.js
CHANGED
|
@@ -106,7 +106,7 @@ class TokenVerifier {
|
|
|
106
106
|
? [groups]
|
|
107
107
|
: [],
|
|
108
108
|
claims,
|
|
109
|
-
...(
|
|
109
|
+
...emailVerified(payload.email_verified),
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
async findKey(issuer, algorithm, kid) {
|
|
@@ -224,4 +224,15 @@ function isSecureUrl(value) {
|
|
|
224
224
|
return false;
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
|
+
// Some issuers send `email_verified` as the string "true" or "false": either says it as
|
|
228
|
+
// much as the boolean does, anything else says nothing
|
|
229
|
+
function emailVerified(value) {
|
|
230
|
+
if (value === true || value === 'true') {
|
|
231
|
+
return { emailVerified: true };
|
|
232
|
+
}
|
|
233
|
+
if (value === false || value === 'false') {
|
|
234
|
+
return { emailVerified: false };
|
|
235
|
+
}
|
|
236
|
+
return {};
|
|
237
|
+
}
|
|
227
238
|
//# sourceMappingURL=oauth.js.map
|
|
@@ -175,7 +175,8 @@ function parse(schema, body) {
|
|
|
175
175
|
/**
|
|
176
176
|
* Who the commit of a push is by: the caller, as their token names them (`name` and
|
|
177
177
|
* `email`, unless the issuer says the address is not verified), else by their subject at the
|
|
178
|
-
* host of their issuer.
|
|
178
|
+
* host of their issuer. Without a name, the local part of the address names them, then the
|
|
179
|
+
* subject. Never what the request says, so a commit can not claim to be
|
|
179
180
|
* somebody else's.
|
|
180
181
|
*/
|
|
181
182
|
function author(principal) {
|
|
@@ -183,11 +184,16 @@ function author(principal) {
|
|
|
183
184
|
.replace(/[<>\0\r\n]/g, '')
|
|
184
185
|
.trim()
|
|
185
186
|
.slice(0, 200);
|
|
186
|
-
const name = clean(principal.claims.name) || clean(principal.claims.preferred_username) || clean(principal.sub);
|
|
187
187
|
// an address the issuer says it did not verify is whatever the caller typed in
|
|
188
188
|
const claimed = principal.emailVerified === false ? '' : clean(principal.claims.email);
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
const email = /^[^\s@]+@[^\s@]+$/.test(claimed) ? claimed : '';
|
|
190
|
+
// a Google service account's token has an address but no name: its local part reads better than the number in sub
|
|
191
|
+
const name = clean(principal.claims.name) ||
|
|
192
|
+
clean(principal.claims.preferred_username) ||
|
|
193
|
+
email.slice(0, email.indexOf('@')) ||
|
|
194
|
+
clean(principal.sub);
|
|
195
|
+
if (email) {
|
|
196
|
+
return { name, email };
|
|
191
197
|
}
|
|
192
198
|
let host = 'hammerkit';
|
|
193
199
|
try {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.packArchive = void 0;
|
|
4
|
+
const tar_1 = require("tar");
|
|
5
|
+
function packArchive(options, files) {
|
|
6
|
+
return (0, tar_1.create)({ ...options, jobs: 1 }, files);
|
|
7
|
+
}
|
|
8
|
+
exports.packArchive = packArchive;
|
|
9
|
+
//# sourceMappingURL=tar.js.map
|
package/package.json
CHANGED