@ogygie/studio 0.27.0 → 0.28.0
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/server.js
CHANGED
|
@@ -1705,6 +1705,26 @@ var EnvironmentsStatusSchema = z6.object({
|
|
|
1705
1705
|
/** release/<date>.<n>, most recent first. */
|
|
1706
1706
|
releases: z6.array(z6.string())
|
|
1707
1707
|
});
|
|
1708
|
+
var EnvironmentReadParamsSchema = z6.object({ environment: EnvironmentNameSchema });
|
|
1709
|
+
var CommitReachSchema = z6.enum(["deployed", "forward", "backward", "unreachable"]);
|
|
1710
|
+
var EnvironmentCommitSchema = z6.object({
|
|
1711
|
+
sha: z6.string(),
|
|
1712
|
+
/** The first line of the message without its `spec: merge` prefix and its `(#n)` suffix. */
|
|
1713
|
+
title: z6.string(),
|
|
1714
|
+
specId: FeatureNameSchema.nullable(),
|
|
1715
|
+
author: z6.string(),
|
|
1716
|
+
authoredAt: z6.string(),
|
|
1717
|
+
releaseTag: z6.string().nullable(),
|
|
1718
|
+
reach: CommitReachSchema,
|
|
1719
|
+
/** The reason, in the client's language. */
|
|
1720
|
+
why: z6.string()
|
|
1721
|
+
});
|
|
1722
|
+
var EnvironmentCommitsSchema = z6.object({
|
|
1723
|
+
environment: EnvironmentNameSchema,
|
|
1724
|
+
ref: z6.string(),
|
|
1725
|
+
deployedSha: z6.string().nullable(),
|
|
1726
|
+
commits: z6.array(EnvironmentCommitSchema).max(30)
|
|
1727
|
+
});
|
|
1708
1728
|
var PromotionInputSchema = z6.object({
|
|
1709
1729
|
sha: z6.string().regex(/^[0-9a-f]{40}$/),
|
|
1710
1730
|
/** Operator only: a step back, forced, with its reason. */
|
|
@@ -3237,6 +3257,48 @@ async function environmentsStatus(deps) {
|
|
|
3237
3257
|
releases: releases.sort().reverse()
|
|
3238
3258
|
};
|
|
3239
3259
|
}
|
|
3260
|
+
var LINE_LENGTH = 30;
|
|
3261
|
+
function commitTitleOf(message) {
|
|
3262
|
+
const firstLine = message.split("\n")[0] ?? "";
|
|
3263
|
+
return firstLine.replace(/^spec: merge /u, "").replace(/\s*\(#\d+\)\s*$/u, "").trim();
|
|
3264
|
+
}
|
|
3265
|
+
function reachOf(environment, index, deployedIndex, stagingIndex) {
|
|
3266
|
+
if (index === deployedIndex) return { reach: "deployed", why: "d\xE9ploy\xE9" };
|
|
3267
|
+
if (environment === "development") return { reach: "unreachable", why: "le d\xE9veloppement suit la branche par d\xE9faut, il ne se promeut pas" };
|
|
3268
|
+
const newer = deployedIndex === -1 || index < deployedIndex;
|
|
3269
|
+
if (environment === "staging") {
|
|
3270
|
+
return newer ? { reach: "forward", why: "avance rapide depuis le d\xE9veloppement" } : { reach: "backward", why: "retour arri\xE8re : op\xE9rateur, avec un motif" };
|
|
3271
|
+
}
|
|
3272
|
+
if (index === stagingIndex && newer) return { reach: "forward", why: "le commit de la pr\xE9production" };
|
|
3273
|
+
if (newer) return { reach: "unreachable", why: stagingIndex !== -1 && index < stagingIndex ? "la pr\xE9production ne l'a pas re\xE7u (PROMOTION_ORDER_VIOLATED)" : "seul le commit de la pr\xE9production est promouvable" };
|
|
3274
|
+
return { reach: "backward", why: "retour arri\xE8re : op\xE9rateur, avec un motif" };
|
|
3275
|
+
}
|
|
3276
|
+
async function environmentCommits(deps, environment) {
|
|
3277
|
+
const ref = environment === "development" ? deps.defaultBranch : ENVIRONMENT_REFS[environment];
|
|
3278
|
+
const [deployedSha, stagingSha, commits, tags] = await Promise.all([
|
|
3279
|
+
deps.deploy.getRefSha(ref),
|
|
3280
|
+
environment === "production" ? deps.deploy.getRefSha(ENVIRONMENT_REFS.staging) : Promise.resolve(null),
|
|
3281
|
+
deps.deploy.listCommits(deps.defaultBranch, LINE_LENGTH),
|
|
3282
|
+
deps.deploy.listReleaseTags("release/")
|
|
3283
|
+
]);
|
|
3284
|
+
const tagOf = new Map(tags.map((tag) => [tag.sha, tag.name]));
|
|
3285
|
+
const deployedIndex = commits.findIndex((commit) => commit.sha === deployedSha);
|
|
3286
|
+
const stagingIndex = stagingSha === null ? -1 : commits.findIndex((commit) => commit.sha === stagingSha);
|
|
3287
|
+
return {
|
|
3288
|
+
environment,
|
|
3289
|
+
ref,
|
|
3290
|
+
deployedSha,
|
|
3291
|
+
commits: commits.map((commit, index) => ({
|
|
3292
|
+
sha: commit.sha,
|
|
3293
|
+
title: commitTitleOf(commit.message),
|
|
3294
|
+
specId: MERGED_SPEC.exec(commit.message.split("\n")[0] ?? "")?.[1] ?? null,
|
|
3295
|
+
author: commit.author,
|
|
3296
|
+
authoredAt: commit.authoredAt,
|
|
3297
|
+
releaseTag: tagOf.get(commit.sha) ?? null,
|
|
3298
|
+
...reachOf(environment, index, deployedIndex, stagingIndex)
|
|
3299
|
+
}))
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3240
3302
|
function pullRequestsOf(commits) {
|
|
3241
3303
|
const included = [];
|
|
3242
3304
|
for (const commit of commits) {
|
|
@@ -3367,6 +3429,15 @@ async function registerPromotionRoutes(app, deps) {
|
|
|
3367
3429
|
return reply.code(200).send(await environmentsStatus(promotionDeps));
|
|
3368
3430
|
}
|
|
3369
3431
|
});
|
|
3432
|
+
route.route({
|
|
3433
|
+
method: "GET",
|
|
3434
|
+
url: "/api/environments/:environment/commits",
|
|
3435
|
+
schema: { params: EnvironmentReadParamsSchema, response: { 200: EnvironmentCommitsSchema } },
|
|
3436
|
+
handler: async (request, reply) => {
|
|
3437
|
+
hostedUserOf(request);
|
|
3438
|
+
return reply.code(200).send(await environmentCommits(promotionDeps, request.params.environment));
|
|
3439
|
+
}
|
|
3440
|
+
});
|
|
3370
3441
|
route.route({
|
|
3371
3442
|
method: "POST",
|
|
3372
3443
|
url: "/api/environments/:environment/promotions",
|
|
@@ -4082,6 +4153,29 @@ function createGithubDeployClient(deps) {
|
|
|
4082
4153
|
commits: (answer?.commits ?? []).map((entry) => ({ sha: entry.sha, message: entry.commit.message, authoredAt: entry.commit.author.date }))
|
|
4083
4154
|
};
|
|
4084
4155
|
},
|
|
4156
|
+
async listReleaseTags(prefix) {
|
|
4157
|
+
const refs = await request("GET", `${repoUrl}/git/matching-refs/tags/${prefix}`, void 0) ?? [];
|
|
4158
|
+
const tags = [];
|
|
4159
|
+
for (const entry of refs) {
|
|
4160
|
+
const name = entry.ref.replace(/^refs\/tags\//u, "");
|
|
4161
|
+
if (entry.object.type !== "tag") {
|
|
4162
|
+
tags.push({ name, sha: entry.object.sha });
|
|
4163
|
+
continue;
|
|
4164
|
+
}
|
|
4165
|
+
const tag = await request("GET", `${repoUrl}/git/tags/${entry.object.sha}`, void 0, true);
|
|
4166
|
+
if (tag !== null) tags.push({ name, sha: tag.object.sha });
|
|
4167
|
+
}
|
|
4168
|
+
return tags;
|
|
4169
|
+
},
|
|
4170
|
+
async listCommits(ref, perPage) {
|
|
4171
|
+
const answer = await request(
|
|
4172
|
+
"GET",
|
|
4173
|
+
`${repoUrl}/commits?sha=${encodeURIComponent(ref)}&per_page=${Math.min(Math.max(perPage, 1), 100)}`,
|
|
4174
|
+
void 0,
|
|
4175
|
+
true
|
|
4176
|
+
);
|
|
4177
|
+
return (answer ?? []).map((entry) => ({ sha: entry.sha, message: entry.commit.message, authoredAt: entry.commit.author.date, author: entry.commit.author.name }));
|
|
4178
|
+
},
|
|
4085
4179
|
async updateRef(ref, sha, force) {
|
|
4086
4180
|
await request("PATCH", `${repoUrl}/git/refs/heads/${encodeURIComponent(ref)}`, { sha, force });
|
|
4087
4181
|
},
|