Improve the build process (#5267)
parent
e99fbf1ab7
commit
fed6e4bdb3
@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
const childProcess = require("child_process");
|
|
||||||
let env = process.env;
|
|
||||||
|
|
||||||
let cmd = process.argv[2];
|
|
||||||
let args = process.argv.slice(3);
|
|
||||||
let replacedArgs = [];
|
|
||||||
|
|
||||||
for (let arg of args) {
|
|
||||||
for (let key in env) {
|
|
||||||
arg = arg.replaceAll(`$${key}`, env[key]);
|
|
||||||
}
|
|
||||||
replacedArgs.push(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
let child = childProcess.spawn(cmd, replacedArgs);
|
|
||||||
child.stdout.pipe(process.stdout);
|
|
||||||
child.stderr.pipe(process.stderr);
|
|
@ -1,6 +0,0 @@
|
|||||||
console.log("Git Push and Publish the release note on github, then press any key to continue");
|
|
||||||
|
|
||||||
process.stdin.setRawMode(true);
|
|
||||||
process.stdin.resume();
|
|
||||||
process.stdin.on("data", process.exit.bind(process, 0));
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
import "dotenv/config";
|
||||||
|
import {
|
||||||
|
ver,
|
||||||
|
buildDist,
|
||||||
|
buildImage,
|
||||||
|
checkDocker,
|
||||||
|
checkTagExists,
|
||||||
|
checkVersionFormat,
|
||||||
|
dryRun,
|
||||||
|
getRepoName,
|
||||||
|
pressAnyKey,
|
||||||
|
execSync, uploadArtifacts,
|
||||||
|
} from "./lib.mjs";
|
||||||
|
import semver from "semver";
|
||||||
|
|
||||||
|
const repoName = getRepoName();
|
||||||
|
const version = process.env.RELEASE_BETA_VERSION;
|
||||||
|
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||||
|
|
||||||
|
console.log("RELEASE_BETA_VERSION:", version);
|
||||||
|
|
||||||
|
if (!githubToken) {
|
||||||
|
console.error("GITHUB_TOKEN is required");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the version is a valid semver
|
||||||
|
checkVersionFormat(version);
|
||||||
|
|
||||||
|
// Check if the semver identifier is "beta"
|
||||||
|
const semverIdentifier = semver.prerelease(version);
|
||||||
|
console.log("Semver identifier:", semverIdentifier);
|
||||||
|
if (semverIdentifier[0] !== "beta") {
|
||||||
|
console.error("VERSION should have a semver identifier of 'beta'");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if docker is running
|
||||||
|
checkDocker();
|
||||||
|
|
||||||
|
// Check if the tag exists
|
||||||
|
await checkTagExists(repoName, version);
|
||||||
|
|
||||||
|
// node extra/beta/update-version.js
|
||||||
|
execSync("node ./extra/beta/update-version.js");
|
||||||
|
|
||||||
|
// Build frontend dist
|
||||||
|
buildDist();
|
||||||
|
|
||||||
|
// Build slim image (rootless)
|
||||||
|
buildImage(repoName, [ "beta-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||||
|
|
||||||
|
// Build full image (rootless)
|
||||||
|
buildImage(repoName, [ "beta-rootless", ver(version, "rootless") ], "rootless");
|
||||||
|
|
||||||
|
// Build slim image
|
||||||
|
buildImage(repoName, [ "beta-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||||
|
|
||||||
|
// Build full image
|
||||||
|
buildImage(repoName, [ "beta", version ], "release");
|
||||||
|
|
||||||
|
await pressAnyKey();
|
||||||
|
|
||||||
|
// npm run upload-artifacts
|
||||||
|
uploadArtifacts();
|
@ -0,0 +1,57 @@
|
|||||||
|
import "dotenv/config";
|
||||||
|
import {
|
||||||
|
ver,
|
||||||
|
buildDist,
|
||||||
|
buildImage,
|
||||||
|
checkDocker,
|
||||||
|
checkTagExists,
|
||||||
|
checkVersionFormat,
|
||||||
|
getRepoName,
|
||||||
|
pressAnyKey, execSync, uploadArtifacts
|
||||||
|
} from "./lib.mjs";
|
||||||
|
|
||||||
|
const repoName = getRepoName();
|
||||||
|
const version = process.env.RELEASE_VERSION;
|
||||||
|
const githubToken = process.env.RELEASE_GITHUB_TOKEN;
|
||||||
|
|
||||||
|
console.log("RELEASE_VERSION:", version);
|
||||||
|
|
||||||
|
if (!githubToken) {
|
||||||
|
console.error("GITHUB_TOKEN is required");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the version is a valid semver
|
||||||
|
checkVersionFormat(version);
|
||||||
|
|
||||||
|
// Check if docker is running
|
||||||
|
checkDocker();
|
||||||
|
|
||||||
|
// Check if the tag exists
|
||||||
|
await checkTagExists(repoName, version);
|
||||||
|
|
||||||
|
// node extra/beta/update-version.js
|
||||||
|
execSync("node extra/update-version.js");
|
||||||
|
|
||||||
|
// Build frontend dist
|
||||||
|
buildDist();
|
||||||
|
|
||||||
|
// Build slim image (rootless)
|
||||||
|
buildImage(repoName, [ "2-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||||
|
|
||||||
|
// Build full image (rootless)
|
||||||
|
buildImage(repoName, [ "2-rootless", ver(version, "rootless") ], "rootless");
|
||||||
|
|
||||||
|
// Build slim image
|
||||||
|
buildImage(repoName, [ "next-slim", "2-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim");
|
||||||
|
|
||||||
|
// Build full image
|
||||||
|
buildImage(repoName, [ "next", "2", version ], "release");
|
||||||
|
|
||||||
|
await pressAnyKey();
|
||||||
|
|
||||||
|
// npm run upload-artifacts
|
||||||
|
uploadArtifacts();
|
||||||
|
|
||||||
|
// node extra/update-wiki-version.js
|
||||||
|
execSync("node extra/update-wiki-version.js");
|
@ -0,0 +1,191 @@
|
|||||||
|
import "dotenv/config";
|
||||||
|
import * as childProcess from "child_process";
|
||||||
|
import semver from "semver";
|
||||||
|
|
||||||
|
export const dryRun = process.env.RELEASE_DRY_RUN === "1";
|
||||||
|
|
||||||
|
if (dryRun) {
|
||||||
|
console.info("Dry run enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if docker is running
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function checkDocker() {
|
||||||
|
try {
|
||||||
|
childProcess.execSync("docker ps");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Docker is not running. Please start docker and try again.");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Docker Hub repository name
|
||||||
|
*/
|
||||||
|
export function getRepoName() {
|
||||||
|
return process.env.RELEASE_REPO_NAME || "louislam/uptime-kuma";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build frontend dist
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function buildDist() {
|
||||||
|
if (!dryRun) {
|
||||||
|
childProcess.execSync("npm run build", { stdio: "inherit" });
|
||||||
|
} else {
|
||||||
|
console.info("[DRY RUN] npm run build");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build docker image and push to Docker Hub
|
||||||
|
* @param {string} repoName Docker Hub repository name
|
||||||
|
* @param {string[]} tags Docker image tags
|
||||||
|
* @param {string} target Dockerfile's target name
|
||||||
|
* @param {string} buildArgs Docker build args
|
||||||
|
* @param {string} dockerfile Path to Dockerfile
|
||||||
|
* @param {string} platform Build platform
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function buildImage(repoName, tags, target, buildArgs = "", dockerfile = "docker/dockerfile", platform = "linux/amd64,linux/arm64,linux/arm/v7") {
|
||||||
|
let args = [
|
||||||
|
"buildx",
|
||||||
|
"build",
|
||||||
|
"-f",
|
||||||
|
dockerfile,
|
||||||
|
"--platform",
|
||||||
|
platform,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add tags
|
||||||
|
for (let tag of tags) {
|
||||||
|
args.push("-t", `${repoName}:${tag}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
args = [
|
||||||
|
...args,
|
||||||
|
"--target",
|
||||||
|
target,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add build args
|
||||||
|
if (buildArgs) {
|
||||||
|
args.push("--build-arg", buildArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
args = [
|
||||||
|
...args,
|
||||||
|
".",
|
||||||
|
"--push",
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!dryRun) {
|
||||||
|
childProcess.spawnSync("docker", args, { stdio: "inherit" });
|
||||||
|
} else {
|
||||||
|
console.log(`[DRY RUN] docker ${args.join(" ")}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the version already exists on Docker Hub
|
||||||
|
* TODO: use semver to compare versions if it is greater than the previous?
|
||||||
|
* @param {string} repoName Docker Hub repository name
|
||||||
|
* @param {string} version Version to check
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export async function checkTagExists(repoName, version) {
|
||||||
|
console.log(`Checking if version ${version} exists on Docker Hub`);
|
||||||
|
|
||||||
|
// Get a list of tags from the Docker Hub repository
|
||||||
|
let tags = [];
|
||||||
|
|
||||||
|
// It is mainly to check my careless mistake that I forgot to update the release version in .env, so `page_size` is set to 100 is enough, I think.
|
||||||
|
const response = await fetch(`https://hub.docker.com/v2/repositories/${repoName}/tags/?page_size=100`);
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
tags = data.results.map((tag) => tag.name);
|
||||||
|
} else {
|
||||||
|
console.error("Failed to get tags from Docker Hub");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the version already exists
|
||||||
|
if (tags.includes(version)) {
|
||||||
|
console.error(`Version ${version} already exists`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the version format
|
||||||
|
* @param {string} version Version to check
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function checkVersionFormat(version) {
|
||||||
|
if (!version) {
|
||||||
|
console.error("VERSION is required");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the version format, it should be a semver and must be like this: "2.0.0-beta.0"
|
||||||
|
if (!semver.valid(version)) {
|
||||||
|
console.error("VERSION is not a valid semver version");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Press any key to continue
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export function pressAnyKey() {
|
||||||
|
console.log("Git Push and Publish the release note on github, then press any key to continue");
|
||||||
|
process.stdin.setRawMode(true);
|
||||||
|
process.stdin.resume();
|
||||||
|
return new Promise(resolve => process.stdin.once("data", data => {
|
||||||
|
process.stdin.setRawMode(false);
|
||||||
|
process.stdin.pause();
|
||||||
|
resolve();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append version identifier
|
||||||
|
* @param {string} version Version
|
||||||
|
* @param {string} identifier Identifier
|
||||||
|
* @returns {string} Version with identifier
|
||||||
|
*/
|
||||||
|
export function ver(version, identifier) {
|
||||||
|
const obj = semver.parse(version);
|
||||||
|
|
||||||
|
if (obj.prerelease.length === 0) {
|
||||||
|
obj.prerelease = [ identifier ];
|
||||||
|
} else {
|
||||||
|
obj.prerelease[0] = [ obj.prerelease[0], identifier ].join("-");
|
||||||
|
}
|
||||||
|
return obj.format();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload artifacts to GitHub
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function uploadArtifacts() {
|
||||||
|
execSync("npm run upload-artifacts");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a command
|
||||||
|
* @param {string} cmd Command to execute
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
export function execSync(cmd) {
|
||||||
|
if (!dryRun) {
|
||||||
|
childProcess.execSync(cmd, { stdio: "inherit" });
|
||||||
|
} else {
|
||||||
|
console.info(`[DRY RUN] ${cmd}`);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
import { buildDist, buildImage, checkDocker, getRepoName } from "./lib.mjs";
|
||||||
|
|
||||||
|
// Docker Hub repository name
|
||||||
|
const repoName = getRepoName();
|
||||||
|
|
||||||
|
// Check if docker is running
|
||||||
|
checkDocker();
|
||||||
|
|
||||||
|
// Build frontend dist (it will build on the host machine, TODO: build on a container?)
|
||||||
|
buildDist();
|
||||||
|
|
||||||
|
// Build full image (rootless)
|
||||||
|
buildImage(repoName, [ "nightly2-rootless" ], "nightly-rootless");
|
||||||
|
|
||||||
|
// Build full image
|
||||||
|
buildImage(repoName, [ "nightly2" ], "nightly");
|
@ -1,9 +0,0 @@
|
|||||||
// Check if docker is running
|
|
||||||
const { exec } = require("child_process");
|
|
||||||
|
|
||||||
exec("docker ps", (err, stdout, stderr) => {
|
|
||||||
if (err) {
|
|
||||||
console.error("Docker is not running. Please start docker and try again.");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
Loading…
Reference in new issue