ci: trigger downstream updates for prereleases (#9008)

* ci: trigger downstream updates for prereleases

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test: cover docs prerelease dispatch

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
This commit is contained in:
Weny Xu
2026-09-03 06:09:57 +00:00
committed by GitHub
parent 15317a131b
commit 25d49ba092
5 changed files with 137 additions and 42 deletions
+3 -3
View File
@@ -715,7 +715,7 @@ jobs:
bump-downstream-repo-versions:
name: Bump downstream repo versions
if: ${{ github.event_name == 'schedule' || ((github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref_type == 'tag' && needs.allocate-runners.outputs.is-current-version-stable == 'true') }}
if: ${{ github.event_name == 'schedule' || ((github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref_type == 'tag' && !contains(github.ref_name, 'nightly')) }}
needs: [allocate-runners, publish-github-release]
runs-on: ubuntu-latest
# Permission reference: https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
@@ -741,7 +741,7 @@ jobs:
bump-helm-charts-version:
name: Bump helm charts version
if: ${{ github.ref_type == 'tag' && !contains(github.ref_name, 'nightly') && github.event_name != 'schedule' && needs.allocate-runners.outputs.is-current-version-stable == 'true' && needs.allocate-runners.outputs.is-current-version-latest == 'true' }}
if: ${{ github.ref_type == 'tag' && !contains(github.ref_name, 'nightly') && github.event_name != 'schedule' && (needs.allocate-runners.outputs.is-current-version-stable != 'true' || needs.allocate-runners.outputs.is-current-version-latest == 'true') }}
needs: [allocate-runners, publish-github-release]
runs-on: ubuntu-latest
permissions:
@@ -762,7 +762,7 @@ jobs:
bump-homebrew-greptime-version:
name: Bump homebrew greptime version
if: ${{ github.ref_type == 'tag' && !contains(github.ref_name, 'nightly') && github.event_name != 'schedule' && needs.allocate-runners.outputs.is-current-version-stable == 'true' && needs.allocate-runners.outputs.is-current-version-latest == 'true' }}
if: ${{ github.ref_type == 'tag' && !contains(github.ref_name, 'nightly') && github.event_name != 'schedule' && (needs.allocate-runners.outputs.is-current-version-stable != 'true' || needs.allocate-runners.outputs.is-current-version-latest == 'true') }}
needs: [allocate-runners, publish-github-release]
runs-on: ubuntu-latest
permissions:
+33 -39
View File
@@ -16,11 +16,12 @@
import * as core from "@actions/core";
import {obtainClient} from "@/common";
import {docsWorkflowDispatch, WorkflowDispatch} from "@/docs-version";
interface RepoConfig {
tokenEnv: string;
repo: string;
workflowLogic: (version: string) => [string, string] | null;
workflowLogic: (version: string) => WorkflowDispatch | null | Promise<WorkflowDispatch | null>;
}
const REPO_CONFIGS: Record<string, RepoConfig> = {
@@ -33,7 +34,10 @@ const REPO_CONFIGS: Record<string, RepoConfig> = {
console.log('Nightly version detected for website, skipping workflow trigger.');
return null;
}
return ['bump-patch-version.yml', version];
return {
workflowId: 'bump-patch-version.yml',
inputs: {version},
};
}
},
demo: {
@@ -45,62 +49,53 @@ const REPO_CONFIGS: Record<string, RepoConfig> = {
console.log('Nightly version detected for demo, skipping workflow trigger.');
return null;
}
return ['bump-patch-version.yml', version];
return {
workflowId: 'bump-patch-version.yml',
inputs: {version},
};
}
},
docs: {
tokenEnv: "DOCS_REPO_TOKEN",
repo: "docs",
workflowLogic: (version: string) => {
// Check if it's a nightly version
workflowLogic: async (version: string): Promise<WorkflowDispatch | null> => {
// Nightly versions do not need the current docs version list.
if (version.includes('nightly')) {
return ['bump-nightly-version.yml', version];
return docsWorkflowDispatch(version, []);
}
// Check for prerelease versions (e.g., 1.0.0-beta.3, 1.0.0-rc.1)
const prereleaseMatch = version.match(/^(\d+)\.(\d+)\.(\d+)-(beta|rc)\.(\d+)$/);
if (prereleaseMatch) {
const [, major, minor, patch, prereleaseType, prereleaseNum] = prereleaseMatch;
// If it's beta.1 and patch version is 0, treat as major version
if (prereleaseType === 'beta' && prereleaseNum === '1' && patch === '0') {
return ['bump-version.yml', `${major}.${minor}`];
}
// Otherwise (beta.x where x > 1, or rc.x), treat as patch version
return ['bump-patch-version.yml', version];
const client = obtainClient('DOCS_REPO_TOKEN');
const {data} = await client.rest.repos.getContent({
owner: 'GreptimeTeam',
repo: 'docs',
path: 'versions.json',
ref: 'main',
});
if (Array.isArray(data) || data.type !== 'file') {
throw new Error('Expected docs versions.json to be a file');
}
const parts = version.split('.');
if (parts.length !== 3) {
throw new Error('Invalid version format');
const versions = JSON.parse(Buffer.from(data.content, 'base64').toString('utf-8'));
if (!Array.isArray(versions) || !versions.every((entry) => typeof entry === 'string')) {
throw new Error('Expected docs versions.json to be a string array');
}
// If patch version (last number) is 0, it's a major version
// Return only major.minor version
if (parts[2] === '0') {
return ['bump-version.yml', `${parts[0]}.${parts[1]}`];
}
// Otherwise it's a patch version, use full version
return ['bump-patch-version.yml', version];
return docsWorkflowDispatch(version, versions);
}
}
};
async function triggerWorkflow(repoConfig: RepoConfig, workflowId: string, version: string) {
async function triggerWorkflow(repoConfig: RepoConfig, dispatch: WorkflowDispatch) {
const client = obtainClient(repoConfig.tokenEnv);
try {
await client.rest.actions.createWorkflowDispatch({
owner: "GreptimeTeam",
repo: repoConfig.repo,
workflow_id: workflowId,
workflow_id: dispatch.workflowId,
ref: "main",
inputs: {
version,
},
inputs: dispatch.inputs,
});
console.log(`Successfully triggered ${workflowId} workflow for ${repoConfig.repo} with version ${version}`);
console.log(`Successfully triggered ${dispatch.workflowId} workflow for ${repoConfig.repo} with version ${dispatch.inputs.version}`);
} catch (error) {
core.setFailed(`Failed to trigger workflow for ${repoConfig.repo}: ${error.message}`);
throw error;
@@ -114,14 +109,13 @@ async function processRepo(repoName: string, version: string) {
}
try {
const workflowResult = repoConfig.workflowLogic(version);
if (workflowResult === null) {
const dispatch = await repoConfig.workflowLogic(version);
if (dispatch === null) {
// Skip this repo (e.g., nightly version for website)
return;
}
const [workflowId, apiVersion] = workflowResult;
await triggerWorkflow(repoConfig, workflowId, apiVersion);
await triggerWorkflow(repoConfig, dispatch);
} catch (error) {
core.setFailed(`Error processing ${repoName} with version ${version}: ${error.message}`);
throw error;
+3
View File
@@ -4,6 +4,9 @@
"description": "Automator for GreptimeDB Repository Management",
"private": true,
"packageManager": "pnpm@8.15.5",
"scripts": {
"test": "tsx --test src/*.test.ts"
},
"dependencies": {
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2023 Greptime Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import assert from 'node:assert/strict';
import test from 'node:test';
import {docsWorkflowDispatch} from './docs-version';
test('cuts a missing documentation line for stable and prerelease versions', () => {
for (const version of ['1.3.0', '1.3.0-alpha.1', '1.3.0-beta.2', '1.3.0-rc.1', '1.3.0-alpha.1+build.7']) {
assert.deepEqual(docsWorkflowDispatch(version, ['1.2']), {
workflowId: 'bump-version.yml',
inputs: {version: '1.3'},
});
}
});
test('bumps the exact version when its documentation line exists', () => {
assert.deepEqual(docsWorkflowDispatch('1.3.0-beta.2', ['1.3']), {
workflowId: 'bump-patch-version.yml',
inputs: {version: '1.3.0-beta.2'},
});
});
test('keeps nightly versions on the nightly workflow', () => {
assert.deepEqual(docsWorkflowDispatch('1.3.0-nightly-20260903', []), {
workflowId: 'bump-nightly-version.yml',
inputs: {version: '1.3.0-nightly-20260903'},
});
});
test('rejects malformed non-nightly versions', () => {
for (const version of ['1.3', 'v1.3.0', '1.3.0-', '1.3.0-alpha..1']) {
assert.throws(() => docsWorkflowDispatch(version, []), /Invalid version format/);
}
});
+49
View File
@@ -0,0 +1,49 @@
/*
* Copyright 2023 Greptime Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export interface WorkflowDispatch {
workflowId: string;
inputs: Record<string, string>;
}
const DOCS_VERSION_RE = /^(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
export function docsWorkflowDispatch(version: string, versions: string[]): WorkflowDispatch {
if (version.includes('nightly')) {
return {
workflowId: 'bump-nightly-version.yml',
inputs: {version},
};
}
const match = version.match(DOCS_VERSION_RE);
if (!match) {
throw new Error('Invalid version format');
}
const docsVersion = `${match[1]}.${match[2]}`;
if (versions.includes(docsVersion)) {
return {
workflowId: 'bump-patch-version.yml',
inputs: {version},
};
}
return {
workflowId: 'bump-version.yml',
inputs: {version: docsVersion},
};
}