@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
  },