feat: Initial clean release of CHM
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
这个提交包含在:
@@ -0,0 +1,137 @@
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { copy, exists, remove, readdir, mkdtemp } from 'fs-extra';
|
||||
import { join, resolve, basename } from 'path';
|
||||
import { tmpdir } from 'os';
|
||||
import { chdir, cwd } from 'process';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { glob } from 'glob';
|
||||
import readRepositoryJson, { BuiltInPluginType, RepositoryData } from './utils/readRepositoryJson';
|
||||
import getPathToPatchFileFor from './utils/getPathToPatchFileFor';
|
||||
import getCurrentCommitHash from './utils/getCurrentCommitHash';
|
||||
import { waitForCliInput } from '@joplin/utils/cli';
|
||||
|
||||
interface Options {
|
||||
outputParentDir: string|null;
|
||||
beforeInstall: (buildDir: string, pluginName: string)=> Promise<void>;
|
||||
beforePatch: ()=> Promise<void>;
|
||||
}
|
||||
|
||||
const buildDefaultPlugins = async (options: Options) => {
|
||||
const pluginRepositoryData = await readRepositoryJson(join(__dirname, 'pluginRepositories.json'));
|
||||
|
||||
for (const pluginId in pluginRepositoryData) {
|
||||
const repositoryData = pluginRepositoryData[pluginId];
|
||||
const outputPath = options.outputParentDir && join(options.outputParentDir, `${pluginId}.jpl`);
|
||||
|
||||
if (repositoryData.type === BuiltInPluginType.Built) {
|
||||
await buildPlugin(pluginId, repositoryData, outputPath, options);
|
||||
} else {
|
||||
if (!outputPath) {
|
||||
console.warn('Skipping NPM plugin,', pluginId, ': missing output path.');
|
||||
continue;
|
||||
}
|
||||
|
||||
logStatus('Copying plugin', pluginId, 'JPL file to', outputPath);
|
||||
await copy(join(__dirname, 'node_modules', repositoryData.package, 'publish', `${pluginId}.jpl`), outputPath);
|
||||
logStatus('Copied.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const logStatus = (...message: string[]) => {
|
||||
const blue = '\x1b[96m';
|
||||
const reset = '\x1b[0m';
|
||||
console.log(blue, ...message, reset);
|
||||
};
|
||||
|
||||
const buildPlugin = async (pluginId: string, repositoryData: RepositoryData, outputPath: string|null, options: Options) => {
|
||||
const pluginSourcesDir = resolve(join(__dirname, 'plugin-sources'));
|
||||
const originalDirectory = cwd();
|
||||
|
||||
const buildDir = await mkdtemp(join(tmpdir(), 'default-plugin-build'));
|
||||
try {
|
||||
logStatus('Building plugin', pluginId, 'at', buildDir);
|
||||
const pluginDir = resolve(join(pluginSourcesDir, pluginId));
|
||||
|
||||
// Clone the repository if not done yet
|
||||
if (!(await exists(pluginDir)) || (await readdir(pluginDir)).length === 0) {
|
||||
logStatus(`Cloning from repository ${repositoryData.cloneUrl}`);
|
||||
await execCommand(['git', 'clone', '--', repositoryData.cloneUrl, pluginDir]);
|
||||
chdir(pluginDir);
|
||||
}
|
||||
|
||||
chdir(pluginDir);
|
||||
const expectedCommitHash = repositoryData.commit;
|
||||
|
||||
logStatus(`Switching to commit ${expectedCommitHash}`);
|
||||
await execCommand(['git', 'switch', repositoryData.branch]);
|
||||
|
||||
try {
|
||||
await execCommand(['git', 'checkout', expectedCommitHash]);
|
||||
} catch (error) {
|
||||
logStatus(`git checkout failed with error ${error}. Fetching...`);
|
||||
await execCommand(['git', 'fetch']);
|
||||
await execCommand(['git', 'checkout', expectedCommitHash]);
|
||||
}
|
||||
|
||||
if (await getCurrentCommitHash() !== expectedCommitHash) {
|
||||
throw new Error(`Unable to checkout commit ${expectedCommitHash}`);
|
||||
}
|
||||
|
||||
logStatus('Copying repository files...');
|
||||
await copy(pluginDir, buildDir, {
|
||||
filter: fileName => {
|
||||
return basename(fileName) !== '.git';
|
||||
},
|
||||
});
|
||||
|
||||
chdir(buildDir);
|
||||
|
||||
logStatus('Initializing repository.');
|
||||
await execCommand('git init . -b main');
|
||||
|
||||
logStatus('Running before-patch hook.');
|
||||
await options.beforePatch();
|
||||
|
||||
const patchFile = getPathToPatchFileFor(pluginId);
|
||||
if (await exists(patchFile)) {
|
||||
logStatus('Applying patch.');
|
||||
await execCommand(['git', 'apply', patchFile]);
|
||||
}
|
||||
|
||||
await options.beforeInstall(buildDir, pluginId);
|
||||
|
||||
logStatus('Installing dependencies.');
|
||||
// `npm install` occasionally crashes on Windows CI with STATUS_STACK_BUFFER_OVERRUN
|
||||
// (exit code 3221226505), hence the retry.
|
||||
await execCommand('npm install --no-audit --no-fund --prefer-offline', { retryCount: 3 });
|
||||
|
||||
const jplFiles = await glob('publish/*.jpl');
|
||||
logStatus(`Found built .jpl files: ${JSON.stringify(jplFiles)}`);
|
||||
|
||||
if (jplFiles.length === 0) {
|
||||
throw new Error(`No published files found in ${buildDir}/publish`);
|
||||
}
|
||||
|
||||
if (outputPath !== null) {
|
||||
const sourceFile = jplFiles[0];
|
||||
logStatus(`Copying built file from ${sourceFile} to ${outputPath}`);
|
||||
await copy(sourceFile, outputPath);
|
||||
} else {
|
||||
console.warn('No output directory specified. Not copying built .jpl files.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.log('Build directory', buildDir);
|
||||
await waitForCliInput();
|
||||
throw error;
|
||||
} finally {
|
||||
chdir(originalDirectory);
|
||||
await remove(buildDir);
|
||||
logStatus('Removed build directory');
|
||||
}
|
||||
};
|
||||
|
||||
export default buildDefaultPlugins;
|
||||
在新工单中引用
屏蔽一个用户