diff --git a/update-overlay/create-pr-if-necessary.js b/update-overlay/create-pr-if-necessary.js index fa07b08..5ed7610 100644 --- a/update-overlay/create-pr-if-necessary.js +++ b/update-overlay/create-pr-if-necessary.js @@ -256,6 +256,46 @@ module.exports = async ({github, context, core}) => { return treeEntries; } + async function removeMissingPluginDirectories() { + const directories = pluginDirectories.split('\n').filter(Boolean); + const queryFields = directories + .map((directory, index) => + `directory${index}: object(expression: "${workspaceCommit}:${directory}/package.json") { ... on Blob { oid } }`, + ) + .join('\n'); + const response = await github.graphql(` + query PluginDirectories($owner: String!, $repo: String!) { + repository(owner: $owner, name: $repo) { + ${queryFields} + } + }`, { + owner: pluginsRepoOwner, + repo: pluginsRepoName, + }); + const existingDirectories = directories.filter((directory, index) => { + if (response.repository?.[`directory${index}`]) { + return true; + } + core.warning( + `Skipping plugin directory ${directory}: it does not exist at source commit ${shortRef(workspaceCommit)}.`, + ); + return false; + }); + + if (existingDirectories.length === 0) { + throw new Error( + `Workspace ${workspaceName} has no plugin directories at source commit ${workspaceCommit}.`, + ); + } + + newPluginsYamlContent = existingDirectories + .map(directory => directory.replace(new RegExp(`^${workspacePath}/(.*)$`), '$1')) + .map(directory => `${directory}:`) + .join('\n') + '\n'; + } + + await removeMissingPluginDirectories(); + const workspaceCheck = await checkWorkspace(overlayRepoBranchName); if (workspaceCheck.status === 'sourceEqual') { if (!force) { diff --git a/update-overlay/create-pr-if-necessary.test.js b/update-overlay/create-pr-if-necessary.test.js new file mode 100644 index 0000000..6e8bb24 --- /dev/null +++ b/update-overlay/create-pr-if-necessary.test.js @@ -0,0 +1,82 @@ +const assert = require('node:assert/strict'); +const test = require('node:test'); + +const updateOverlay = require('./create-pr-if-necessary.js'); + +test('omits directories absent from the selected source commit', async () => { + let createdTree; + const core = { + getInput(name) { + return { + overlay_repo: 'redhat-developer/rhdh-plugin-export-overlays', + plugins_repo: 'redhat-developer/rhdh-plugins', + overlay_repo_branch_name: 'main', + target_pr_branch_name: 'workspaces/main__homepage', + backstage_version: '1.54.0', + match_type: 'exact', + workspace_name: 'homepage', + workspace_commit: '90a173c', + plugins_repo_flat: 'false', + plugin_directories: [ + 'workspaces/homepage/plugins/homepage', + 'workspaces/homepage/plugins/dynamic-home-page', + ].join('\n'), + allow_workspace_addition: 'true', + pr_to_update: '', + workspace_json: JSON.stringify({ plugins: [] }), + force: 'false', + }[name]; + }, + info() {}, + warning() {}, + debug() {}, + summary: { + addHeading() { return this; }, + addLink() { return this; }, + addRaw() { return this; }, + async write() {}, + }, + }; + const github = { + async graphql(query) { + if (query.includes('query PluginDirectories')) { + return { repository: { directory0: { oid: 'present' }, directory1: null } }; + } + return { + repository: { + pluginsList: { text: 'plugins/homepage:\n' }, + sourceJson: { + text: JSON.stringify({ + repo: 'https://github.com/redhat-developer/rhdh-plugins', + 'repo-ref': 'old-commit', + 'repo-flat': false, + }), + }, + backstageJson: null, + metadataTree: { entries: [] }, + }, + }; + }, + rest: { + pulls: { + async list() { return { status: 200, data: [] }; }, + async create() { return { data: { html_url: 'https://example.test/pr/1' } }; }, + }, + repos: { + async compareCommits() { return { data: { status: 'ahead', html_url: 'https://example.test/compare' } }; }, + async listCommits() { return { data: [{ sha: 'base', commit: { tree: { sha: 'tree' } } }] }; }, + }, + git: { + async getRef() { const error = new Error('missing'); error.status = 404; throw error; }, + async createTree(options) { createdTree = options; return { data: { sha: 'new-tree' } }; }, + async createCommit() { return { data: { sha: 'new-commit' } }; }, + async createRef() {}, + }, + }, + }; + + await updateOverlay({ github, context: {}, core }); + + const pluginsList = createdTree.tree.find(entry => entry.path.endsWith('plugins-list.yaml')); + assert.equal(pluginsList.content, 'plugins/homepage:\n'); +}); diff --git a/update-overlay/package.json b/update-overlay/package.json index 65bade2..b974197 100644 --- a/update-overlay/package.json +++ b/update-overlay/package.json @@ -2,6 +2,9 @@ "name": "update-overlay", "version": "1.0.0", "private": true, + "scripts": { + "test": "node --test" + }, "dependencies": { "yaml": "^2.8.0" }