Extract CI scripts in separate files

This commit is contained in:
Quentin Gliech
2025-02-06 11:27:25 +01:00
parent 058a301e3b
commit 690b88c668
13 changed files with 268 additions and 155 deletions

2
.github/scripts/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
node_modules/
package-lock.json

71
.github/scripts/commit-and-tag.cjs vendored Normal file
View File

@@ -0,0 +1,71 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const fs = require("node:fs/promises");
const { owner, repo } = context.repo;
const version = process.env.VERSION;
const parent = context.sha;
if (!version) throw new Error("VERSION is not defined");
const files = [
"Cargo.toml",
"Cargo.lock",
"tools/syn2mas/package.json",
"tools/syn2mas/package-lock.json",
];
/** @type {{path: string, mode: "100644", type: "blob", sha: string}[]} */
const tree = [];
for (const file of files) {
const content = await fs.readFile(file);
const blob = await github.rest.git.createBlob({
owner,
repo,
content: content.toString("base64"),
encoding: "base64",
});
console.log(`Created blob for ${file}:`, blob.data.url);
tree.push({
path: file,
mode: "100644",
type: "blob",
sha: blob.data.sha,
});
}
const treeObject = await github.rest.git.createTree({
owner,
repo,
tree,
base_tree: parent,
});
console.log("Created tree:", treeObject.data.url);
const commit = await github.rest.git.createCommit({
owner,
repo,
message: version,
parents: [parent],
tree: treeObject.data.sha,
});
console.log("Created commit:", commit.data.url);
const tag = await github.rest.git.createTag({
owner,
repo,
tag: `v${version}`,
message: version,
type: "commit",
object: commit.data.sha,
});
console.log("Created tag:", tag.data.url);
return { commit: commit.data.sha, tag: tag.data.sha };
};

View File

@@ -0,0 +1,22 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const { owner, repo } = context.repo;
const branch = process.env.BRANCH;
const sha = process.env.SHA;
if (!sha) throw new Error("SHA is not defined");
await github.rest.git.createRef({
owner,
repo,
ref: `refs/heads/${branch}`,
sha,
});
console.log(`Created branch ${branch} from ${sha}`);
};

24
.github/scripts/create-version-tag.cjs vendored Normal file
View File

@@ -0,0 +1,24 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const { owner, repo } = context.repo;
const version = process.env.VERSION;
const tagSha = process.env.TAG_SHA;
if (!version) throw new Error("VERSION is not defined");
if (!tagSha) throw new Error("TAG_SHA is not defined");
const tag = await github.rest.git.createRef({
owner,
repo,
ref: `refs/tags/v${version}`,
sha: tagSha,
});
console.log("Created tag ref:", tag.data.url);
};

60
.github/scripts/merge-back.cjs vendored Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const { owner, repo } = context.repo;
const sha = process.env.SHA;
const branch = `ref-merge/${sha}`;
if (!sha) throw new Error("SHA is not defined");
await github.rest.git.createRef({
owner,
repo,
ref: `refs/heads/${branch}`,
sha,
});
console.log(`Created branch ${branch} to ${sha}`);
// Create a PR to merge the branch back to main
const pr = await github.rest.pulls.create({
owner,
repo,
head: branch,
base: "main",
title: "Automatic merge back to main",
body: "This pull request was automatically created by the release workflow. It merges the release branch back to main.",
maintainer_can_modify: true,
});
console.log(
`Created pull request #${pr.data.number} to merge the release branch back to main`,
);
console.log(`PR URL: ${pr.data.html_url}`);
// Add the `T-Task` label to the PR
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.data.number,
labels: ["T-Task"],
});
// Enable auto-merge on the PR
await github.graphql(
`
mutation AutoMerge($id: ID!) {
enablePullRequestAutoMerge(input: {
pullRequestId: $id,
mergeMethod: MERGE,
}) {
clientMutationId
}
}
`,
{ id: pr.data.node_id },
);
};

7
.github/scripts/package.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
"private": true,
"devDependencies": {
"@actions/github-script": "github:actions/github-script",
"typescript": "^5.7.3"
}
}

View File

@@ -0,0 +1,22 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const { owner, repo } = context.repo;
const branch = process.env.BRANCH;
const sha = process.env.SHA;
if (!sha) throw new Error("SHA is not defined");
await github.rest.git.updateRef({
owner,
repo,
ref: `heads/${branch}`,
sha,
});
console.log(`Updated branch ${branch} to ${sha}`);
};

21
.github/scripts/update-unstable-tag.cjs vendored Normal file
View File

@@ -0,0 +1,21 @@
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
// @ts-check
/** @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments */
module.exports = async ({ github, context }) => {
const { owner, repo } = context.repo;
const sha = context.sha;
const tag = await github.rest.git.updateRef({
owner,
repo,
force: true,
ref: "tags/unstable",
sha,
});
console.log("Updated tag ref:", tag.data.url);
};

View File

@@ -444,21 +444,18 @@ jobs:
path: artifacts
merge-multiple: true
- name: Checkout the code
uses: actions/checkout@v4.2.2
with:
sparse-checkout: |
.github/scripts
- name: Update unstable git tag
uses: actions/github-script@v7.0.1
with:
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const sha = process.env.GITHUB_SHA;
const tag = await github.rest.git.updateRef({
owner,
repo,
force: true,
ref: 'tags/unstable',
sha,
});
console.log("Updated tag ref:", tag.data.url);
const script = require('./.github/scripts/update-unstable-tag.cjs');
await script({ core, github, context });
- name: Update unstable release
uses: softprops/action-gh-release@v2

View File

@@ -14,7 +14,16 @@ jobs:
name: Merge back the reference to main
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- name: Checkout the code
uses: actions/checkout@v4
with:
sparse-checkout: |
.github/scripts
- name: Push branch and open a PR
uses: actions/github-script@v7.0.1
env:
@@ -22,51 +31,5 @@ jobs:
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
const sha = process.env.SHA;
const branch = `ref-merge/${sha}`;
const ref = `heads/${branch}`;
await github.rest.git.createRef({
owner,
repo,
ref,
sha,
});
console.log(`Created branch ${branch} to ${sha}`);
// Create a PR to merge the branch back to main
const pr = await github.rest.pulls.create({
owner,
repo,
head: branch,
base: 'main',
title: `Automatic merge back to main`,
body: `This pull request was automatically created by the release workflow. It merges the release branch back to main.`,
maintainer_can_modify: true,
});
console.log(`Created pull request #${pr.data.number} to merge the release branch back to main`);
console.log(`PR URL: ${pr.data.html_url}`);
// Add the `T-Task` label to the PR
await github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.data.number,
labels: ['T-Task'],
});
// Enable auto-merge on the PR
await github.graphql(
`
mutation AutoMerge($id: ID!) {
enablePullRequestAutoMerge(input: {
pullRequestId: $id,
mergeMethod: MERGE,
}) {
clientMutationId
}
}
`,
{ id: pr.data.node_id },
);
const script = require('./.github/scripts/merge-back.js');
await script({ core, github, context });

View File

@@ -89,6 +89,12 @@ jobs:
needs: [tag, compute-version, localazy]
steps:
- name: Checkout the code
uses: actions/checkout@v4.2.2
with:
sparse-checkout: |
.github/scripts
- name: Create a new release branch
uses: actions/github-script@v7.0.1
env:
@@ -97,15 +103,5 @@ jobs:
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
const branch = process.env.BRANCH;
const sha = process.env.SHA;
const ref = `refs/heads/${branch}`;
await github.rest.git.createRef({
owner,
repo,
ref,
sha,
});
console.log(`Created branch ${branch} from ${sha}`);
const script = require('./.github/scripts/create-release-branch.js');
await script({ core, github, context });

View File

@@ -70,6 +70,12 @@ jobs:
needs: [tag, compute-version]
steps:
- name: Checkout the code
uses: actions/checkout@v4.2.2
with:
sparse-checkout: |
.github/scripts
- name: Update the release branch
uses: actions/github-script@v7.0.1
env:
@@ -78,15 +84,5 @@ jobs:
with:
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/');
const branch = process.env.BRANCH;
const sha = process.env.SHA;
const ref = `heads/${branch}`;
await github.rest.git.updateRef({
owner,
repo,
ref,
sha,
});
console.log(`Updated branch ${branch} to ${sha}`);
const script = require('./.github/scripts/update-release-branch.cjs');
await script({ core, github, context });

View File

@@ -53,65 +53,8 @@ jobs:
# Commit & tag with the actions token, so that they get signed
# This returns the commit sha and the tag object sha
script: |
const fs = require("fs/promises");
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const version = process.env.VERSION;
const parent = context.sha;
const files = [
"Cargo.toml",
"Cargo.lock",
"tools/syn2mas/package.json",
"tools/syn2mas/package-lock.json",
];
const tree = [];
for (const file of files) {
const content = await fs.readFile(file);
const blob = await github.rest.git.createBlob({
owner,
repo,
content: content.toString("base64"),
encoding: "base64",
});
console.log(`Created blob for ${file}:`, blob.data.url);
tree.push({
path: file,
mode: "100644",
type: "blob",
sha: blob.data.sha,
});
}
const treeObject = await github.rest.git.createTree({
owner,
repo,
tree,
base_tree: parent,
});
console.log("Created tree:", treeObject.data.url);
const commit = await github.rest.git.createCommit({
owner,
repo,
message: version,
parents: [parent],
tree: treeObject.data.sha,
});
console.log("Created commit:", commit.data.url);
const tag = await github.rest.git.createTag({
owner,
repo,
tag: `v${version}`,
message: version,
type: "commit",
object: commit.data.sha,
});
console.log("Created tag:", tag.data.url);
return { commit: commit.data.sha, tag: tag.data.sha };
const script = require('./.github/scripts/commit-and-tag.cjs');
return await script({ core, github, context });
- name: Update the refs
uses: actions/github-script@v7.0.1
@@ -123,16 +66,5 @@ jobs:
# Update the refs with the bot token, so that workflows are triggered
github-token: ${{ secrets.BOT_GITHUB_TOKEN }}
script: |
const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
const version = process.env.VERSION;
const commit = process.env.COMMIT_SHA;
const tagSha = process.env.TAG_SHA;
const branch = process.env.GITHUB_REF_NAME;
const tag = await github.rest.git.createRef({
owner,
repo,
ref: `refs/tags/v${version}`,
sha: tagSha,
});
console.log("Created tag ref:", tag.data.url);
const script = require('./.github/scripts/create-version-tag.cjs');
await script({ core, github, context });