chore: remove unused tools/* content (#12456)

Signed-off-by: axel7083 <42176370+axel7083@users.noreply.github.com>
This commit is contained in:
axel7083 2025-05-13 12:20:07 +02:00 committed by GitHub
parent 9fedaec24b
commit c692b9b4e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 0 additions and 671 deletions

View file

@ -1,65 +0,0 @@
#
# Copyright (C) 2023-2024 Red Hat, Inc.
#
# 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.
#
# SPDX-License-Identifier: Apache-2.0
name: release-notes
on:
workflow_dispatch:
inputs:
milestone:
description: 'Milestone to generate release notes from (title of the milestone eg 1.0.0)'
required: true
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
jobs:
build:
name: Generate release notes
runs-on: ubuntu-24.04
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
name: Install pnpm
with:
run_install: false
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22
cache: 'pnpm'
- name: Execute pnpm
run: pnpm install
- name: Build
run: |
cd tools
pnpm build
- name: Generate the release notes document
run: |
node tools/dist/release-notes-generator.cjs --milestone ${{ github.event.inputs.milestone }} >release-notes.md
- name: Archive the generated release notes
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: release-notes
path: release-notes.md

View file

@ -51,7 +51,6 @@ const TYPESCRIPT_PROJECTS = [
'./extensions/*/tsconfig.json',
'./extensions/*/packages/*/tsconfig.json',
'./tests/playwright/tsconfig.json',
'./tools/tsconfig.json',
'./storybook/tsconfig.json',
];

View file

@ -69,7 +69,6 @@
"test:extensions:kubectl-cli": "vitest --run --project=kubectl-cli --passWithNoTests",
"test:renderer": "pnpm run build:preload:types && pnpm run build:ui && vitest --run --project=renderer --passWithNoTests",
"test:ui": "vitest --run --project=@podman-desktop/ui-svelte --passWithNoTests",
"test:tools": "vitest --run --project=release-notes-generator --passWithNoTests",
"test:scripts:stylesheet": "vitest --run --project=scripts --passWithNoTests",
"test:watch": "vitest watch",
"test:website": "vitest --run --project=docs --passWithNoTests",

View file

@ -911,19 +911,6 @@ importers:
specifier: ^3.1.3
version: 3.1.3(@types/debug@4.1.12)(@types/node@22.13.10)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(msw@2.8.2(@types/node@22.13.10)(typescript@5.8.3))(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.1)
tools:
dependencies:
'@octokit/graphql':
specifier: ^8.2.2
version: 8.2.2
devDependencies:
typescript:
specifier: ^5.8.3
version: 5.8.3
vitest:
specifier: ^3.1.3
version: 3.1.3(@types/debug@4.1.12)(@types/node@22.15.16)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(msw@2.8.2(@types/node@22.15.16)(typescript@5.8.3))(terser@5.36.0)(tsx@4.19.4)(yaml@2.7.1)
website:
dependencies:
'@docusaurus/core':

View file

@ -5,7 +5,6 @@ packages:
- 'storybook'
- 'website'
- 'website-argos'
- 'tools'
- 'tests/*'
- 'scripts'
onlyBuiltDependencies:

View file

@ -1,19 +0,0 @@
{
"name": "release-notes-generator",
"version": "1.0.0",
"description": "Generates release notes",
"main": "index.js",
"type": "module",
"author": "The Podman Desktop team",
"license": "MIT",
"scripts": {
"build": "vite build"
},
"dependencies": {
"@octokit/graphql": "^8.2.2"
},
"devDependencies": {
"typescript": "^5.8.3",
"vitest": "^3.1.3"
}
}

View file

@ -1,236 +0,0 @@
/**********************************************************************
* Copyright (C) 2023 Red Hat, Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/
import { graphql } from '@octokit/graphql';
import type { Mock } from 'vitest';
import { beforeEach, expect, test, vi } from 'vitest';
import { Generator, RELEASE_NOTES_SECTION_TAG } from './generator';
vi.mock('@octokit/graphql', async () => {
return {
graphql: vi.fn(),
};
});
beforeEach(() => {
graphql.defaults = vi.fn().mockReturnValue(graphql);
});
test('Ensure error is returned if network error', async () => {
(graphql as unknown as Mock).mockRejectedValue(new Error('Custom error'));
try {
const generator = new Generator('token', 'org', 'repo', false, undefined);
await generator.generate();
} catch (err) {
expect(err).to.be.a('Error');
expect(err).toBeDefined();
}
});
test('Ensure error is returned if no milestone', async () => {
(graphql as unknown as Mock).mockResolvedValue({});
try {
const generator = new Generator('token', 'org', 'repo', false, undefined);
await generator.generate();
} catch (err) {
expect(err).to.be.a('Error');
expect(err).toBeDefined();
}
});
test('Ensure empty if no pull requests', async () => {
let index = 0;
(graphql as unknown as Mock).mockImplementation(async () => {
if (++index === 1) {
return { organization: { repository: { milestones: { nodes: [{ title: '1.0' }] } } } };
} else if (index === 2) {
return EMPTY_PULL_REQUESTS_RESPONSE;
}
});
const generator = new Generator('token', 'org', 'repo', false, undefined);
const result = await generator.generate();
expect(result).toBe('');
});
const EMPTY_PULL_REQUESTS_RESPONSE = {
organization: { repository: { milestones: { nodes: [{ pullRequests: { nodes: [] } }] } } },
};
test('Ensure Other category if pull request without conventional commit', async () => {
let index = 0;
(graphql as unknown as Mock).mockImplementation(async () => {
if (++index === 1) {
return { organization: { repository: { milestones: { nodes: [{ title: '1.0' }] } } } };
} else if (index === 2) {
return {
organization: {
repository: {
milestones: {
nodes: [
{
pullRequests: {
nodes: [
{
title: 'First PR',
body: 'PR description' + RELEASE_NOTES_SECTION_TAG + 'section1' + RELEASE_NOTES_SECTION_TAG,
number: 1,
permalink: '',
},
],
},
},
],
},
},
},
};
} else {
return EMPTY_PULL_REQUESTS_RESPONSE;
}
});
const generator = new Generator('token', 'org', 'repo', false, undefined);
const result = await generator.generate();
expect(result).toContain('### Other');
expect(result).toContain('- First PR');
expect(result).toContain('section1');
});
test('Ensure all sections are extracted', async () => {
let index = 0;
(graphql as unknown as Mock).mockImplementation(async () => {
if (++index === 1) {
return { organization: { repository: { milestones: { nodes: [{ title: '1.0' }] } } } };
} else if (index === 2) {
return {
organization: {
repository: {
milestones: {
nodes: [
{
pullRequests: {
nodes: [
{
title: 'First PR',
body:
'PR description' +
RELEASE_NOTES_SECTION_TAG +
'section1' +
RELEASE_NOTES_SECTION_TAG +
'see' +
RELEASE_NOTES_SECTION_TAG +
'section2' +
RELEASE_NOTES_SECTION_TAG,
number: 1,
permalink: '',
},
],
},
},
],
},
},
},
};
} else {
return EMPTY_PULL_REQUESTS_RESPONSE;
}
});
const generator = new Generator('token', 'org', 'repo', false, undefined);
const result = await generator.generate();
expect(result).toContain('### Other');
expect(result).toContain('- First PR');
expect(result).toContain('section1');
expect(result).toContain('section2');
});
test('Ensure category from pull request conventional commit', async () => {
let index = 0;
(graphql as unknown as Mock).mockImplementation(async () => {
if (++index === 1) {
return { organization: { repository: { milestones: { nodes: [{ title: '1.0' }] } } } };
} else if (index === 2) {
return {
organization: {
repository: {
milestones: {
nodes: [
{
pullRequests: {
nodes: [
{
title: 'fix: First PR',
body: 'PR description' + RELEASE_NOTES_SECTION_TAG + 'section1' + RELEASE_NOTES_SECTION_TAG,
number: 1,
permalink: '',
},
],
},
},
],
},
},
},
};
} else {
return EMPTY_PULL_REQUESTS_RESPONSE;
}
});
const generator = new Generator('token', 'org', 'repo', false, undefined);
const result = await generator.generate();
expect(result).toContain('### Bug Fixes');
expect(result).toContain('- First PR');
expect(result).toContain('section1');
});
test('Ensure unterminated section is extracted', async () => {
let index = 0;
(graphql as unknown as Mock).mockImplementation(async () => {
if (++index === 1) {
return { organization: { repository: { milestones: { nodes: [{ title: '1.0' }] } } } };
} else if (index === 2) {
return {
organization: {
repository: {
milestones: {
nodes: [
{
pullRequests: {
nodes: [
{
title: 'fix: First PR',
body: 'PR description' + RELEASE_NOTES_SECTION_TAG + 'section1',
number: 1,
permalink: '',
},
],
},
},
],
},
},
},
};
} else {
return EMPTY_PULL_REQUESTS_RESPONSE;
}
});
const generator = new Generator('token', 'org', 'repo', false, undefined);
const result = await generator.generate();
expect(result).toContain('### Bug Fixes');
expect(result).toContain('- First PR');
expect(result).toContain('section1');
});

View file

@ -1,201 +0,0 @@
/**********************************************************************
* Copyright (C) 2023 Red Hat, Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/
import { graphql } from '@octokit/graphql';
export const RELEASE_NOTES_SECTION_TAG = '// release-notes';
const DEFAULT_MAPPINGS = new Map<string, string>([
['feat', 'Features'],
['fix', 'Bug Fixes'],
['docs', 'Documentation'],
['chore', 'Chore'],
]);
const DEFAULT_CATEGORY = 'Other';
interface PullRequestInfo {
title: string;
link: string;
number: number;
sections: string[];
}
export class Generator {
private client;
constructor(
private token: string,
private organization: string,
private repo: string,
private isUser: boolean,
private milestone: string | undefined,
) {
this.client = graphql.defaults({
headers: {
authorization: `token ${token}`,
},
});
}
private getMilestoneQuery(): string {
return `query {
${this.isUser ? 'user' : 'organization'}(login: "${this.organization}") {
repository(name: "${this.repo}") {
milestones(last:1, states: OPEN${this.milestone ? ', query: "' + `${this.milestone}` + '"' : ''}) {
nodes {
id
title
}
}
}
}
}`;
}
private getPullRequestsQuery(milestone: string, latestPR?: string): string {
return `query {
${this.isUser ? 'user' : 'organization'}(login: "${this.organization}") {
repository(name: "${this.repo}") {
milestones(last:1, states: OPEN, query: "${milestone}") {
nodes {
pullRequests(first: 100, states: MERGED${latestPR ? ', after: "' + `${latestPR}` + '"' : ''}) {
pageInfo {
endCursor
startCursor
}
nodes {
title
state
id
number
body
permalink
}
}
}
}
}
}
}`;
}
async getMilestone(): Promise<{ title: string }> {
const query = this.getMilestoneQuery();
const result = await this.client(query);
if (this.isUser) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (result as any).user?.repository?.milestones?.nodes[0];
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (result as any).organization?.repository?.milestones?.nodes[0];
}
}
async getPullRequests(
milestone: string,
latestPr?: string,
): Promise<{
pageInfo?: { endCursor?: string };
nodes?: { body: string; title: string; permalink: string; number: number }[];
}> {
const query = this.getPullRequestsQuery(milestone, latestPr);
const result = await this.client(query);
if (this.isUser) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (result as any).user?.repository?.milestones?.nodes[0].pullRequests;
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (result as any).organization?.repository?.milestones?.nodes[0].pullRequests;
}
}
public getReleaseNotesSections(input: string): string[] {
const sections = [];
let index = 0;
while ((index = input.indexOf(RELEASE_NOTES_SECTION_TAG, index)) !== -1) {
const endIndex = input.indexOf(RELEASE_NOTES_SECTION_TAG, index + RELEASE_NOTES_SECTION_TAG.length);
if (endIndex !== -1) {
sections.push(input.substring(index + RELEASE_NOTES_SECTION_TAG.length, endIndex));
index = endIndex + RELEASE_NOTES_SECTION_TAG.length;
} else {
sections.push(input.substring(index + RELEASE_NOTES_SECTION_TAG.length));
break;
}
}
return sections;
}
private processPullRequestTitle(title: string): { category: string; title: string } {
const index = title.indexOf(':');
if (index > 0) {
let category: string | undefined = title.substring(0, index);
const subIndex = category.indexOf('(');
if (subIndex > 0) {
category = category.substring(0, subIndex);
}
title = title.substring(index + 1).trim();
category = DEFAULT_MAPPINGS.get(category);
category ??= DEFAULT_CATEGORY;
return { category, title };
} else {
return { category: DEFAULT_CATEGORY, title };
}
}
async generate(): Promise<string> {
const milestone = await this.getMilestone();
if (milestone) {
const prInfos = new Map<string, PullRequestInfo[]>();
let latestPR = undefined;
let done = false;
while (!done) {
const pullRequests = await this.getPullRequests(milestone.title, latestPR);
latestPR = pullRequests?.pageInfo?.endCursor;
if (pullRequests?.nodes?.length) {
for (const pr of pullRequests.nodes) {
if (pr.body && pr.title) {
const sections = this.getReleaseNotesSections(pr.body);
if (sections.length > 0) {
const { category, title } = this.processPullRequestTitle(pr.title);
let categoryInfos = prInfos.get(category);
if (!categoryInfos) {
categoryInfos = [];
prInfos.set(category, categoryInfos);
}
categoryInfos.push({ title, link: pr.permalink, number: pr.number, sections });
}
}
}
} else {
done = true;
}
}
let content = '';
prInfos.forEach((prInfos1, category) => {
content += `### ${category}\n`;
prInfos1.forEach(prInfo => {
content += ` - ${prInfo.title} [(#${prInfo.number})](${prInfo.link})\n`;
content += prInfo.sections.join('');
content += '\n';
});
});
return content;
} else {
throw new Error(this.milestone ? `Milestone ${this.milestone} not found` : 'no milestone found');
}
}
}

View file

@ -1,58 +0,0 @@
/**********************************************************************
* Copyright (C) 2023 Red Hat, Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/
import { Generator } from './generator';
async function run(): Promise<void> {
let token = process.env.GITHUB_TOKEN;
token ??= process.env.GH_TOKEN;
const args = process.argv.slice(2);
let organization = 'containers';
let repo = 'podman-desktop';
let isUser = false;
let milestone = undefined;
for (let i = 0; i < args.length; i++) {
if (args[i] === '--token') {
token = args[++i];
} else if (args[i] === '--org') {
organization = args[++i];
} else if (args[i] === '--user') {
organization = args[++i];
isUser = true;
} else if (args[i] === '--repo') {
repo = args[++i];
} else if (args[i] === '--milestone') {
milestone = args[++i];
}
}
if (token) {
const rn = await new Generator(token, organization, repo, isUser, milestone).generate();
console.log(`${rn}`);
} else {
console.log('No token found use either GITHUB_TOKEN or pass it as an argument');
}
}
run()
.then(() => {
process.exit(0);
})
.catch((err: unknown) => {
console.error(err);
process.exit(1);
});

View file

@ -1,14 +0,0 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
"target": "esnext",
"module": "esnext",
"moduleResolution": "Node",
"sourceMap": true,
"outDir": "./dist",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}

View file

@ -1,62 +0,0 @@
/**********************************************************************
* Copyright (C) 2023-2025 Red Hat, Inc.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
***********************************************************************/
import { join } from 'path';
import { builtinModules } from 'module';
const PACKAGE_ROOT = __dirname;
/**
* @type {import('vite').UserConfig}
* @see https://vitejs.dev/config/
*/
const config = {
mode: process.env.MODE,
root: PACKAGE_ROOT,
envDir: process.cwd(),
resolve: {
alias: {
'/@/': join(PACKAGE_ROOT, 'src') + '/',
},
},
build: {
sourcemap: 'inline',
target: 'esnext',
outDir: 'dist',
assetsDir: '.',
minify: process.env.MODE === 'production' ? 'esbuild' : false,
lib: {
entry: 'src/release-notes-generator.ts',
formats: ['cjs'],
},
rollupOptions: {
external: [...builtinModules.flatMap(p => [p, `node:${p}`])],
output: {
entryFileNames: '[name].cjs',
},
},
emptyOutDir: true,
reportCompressedSize: false,
},
test: {
environment: 'node',
include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
},
};
export default config;