Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/update-plugins-repo-refs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,11 @@ jobs:
core.setOutput('plugins-repo', workspace.repo);
core.setOutput('plugins-repo-flat', workspace.flat);
core.setOutput('plugin-directories', workspace.plugins.map((plugin) => plugin.directory).join('\n'));
const pluginVersions = {};
for (const plugin of workspace.plugins) {
pluginVersions[plugin.name] = plugin.version;
}
core.setOutput('plugin-versions', JSON.stringify(pluginVersions));
Comment on lines +575 to +579
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering we are likely to use other workspace metadata, we might consider simply passing in the entire workspace JSON.

@davidfestal @rostalan wdyt?

return {};

- name: Create PR if necessary
Expand All @@ -588,6 +593,7 @@ jobs:
plugins-repo: ${{ steps.prepare.outputs.plugins-repo }}
plugins-repo-flat: ${{ steps.prepare.outputs.plugins-repo-flat }}
plugin-directories: ${{ steps.prepare.outputs.plugin-directories }}
plugin-versions: ${{ steps.prepare.outputs.plugin-versions }}
allow-workspace-addition: ${{ inputs.allow-workspace-addition }}
pr-to-update: ${{ inputs.pr-to-update }}

Expand Down
6 changes: 6 additions & 0 deletions update-overlay/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ inputs:
required: false
default: ""

plugin-versions:
description: "JSON object mapping packageName to version for metadata updates"
required: false
default: "{}"

runs:
using: "composite"
steps:
Expand All @@ -69,6 +74,7 @@ runs:
INPUT_PLUGIN_DIRECTORIES: ${{ inputs.plugin-directories }}
INPUT_ALLOW_WORKSPACE_ADDITION: ${{ inputs.allow-workspace-addition }}
INPUT_PR_TO_UPDATE: ${{ inputs.pr-to-update }}
INPUT_PLUGIN_VERSIONS: ${{ inputs.plugin-versions }}

with:
retries: 4
Expand Down
98 changes: 98 additions & 0 deletions update-overlay/create-pr-if-necessary.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
const pluginDirectories = core.getInput('plugin_directories');
const allowWorkspaceAddition = core.getInput('allow_workspace_addition');
const prToUpdate = core.getInput('pr_to_update');
const pluginVersions = JSON.parse(core.getInput('plugin_versions') || '{}');

const updateCommitLabel = 'needs-commit-update';

Expand Down Expand Up @@ -134,6 +135,97 @@
}
}

/**
* Read metadata/*.yaml files from the overlay repo via GraphQL,
* update spec.version and spec.dynamicArtifact (oci://ghcr.io) to match
* the plugin versions discovered from NPM.
* @param {string} branchName
* @returns {Promise<Array<{path: string, mode: string, content: string}>>}
*/
async function updateMetadataFiles(branchName) {

Check failure on line 145 in update-overlay/create-pr-if-necessary.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 20 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=redhat-developer_rhdh-plugin-export-utils&issues=AZzTsv1RULVembEs1laR&open=AZzTsv1RULVembEs1laR&pullRequest=116
if (Object.keys(pluginVersions).length === 0) {
return [];
}

/** @type {{ repository: { metadataTree: { entries: Array<{name: string, object: {text: string} | null}> } | null } }} */
const metadataResponse = await github.graphql(`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already run into problems with rate limiting at the moment, so it would be best to roll this up into the existing query, and then pass it along to the updateMetadataFiles() function as an argument. Let's also use a re-usable type for this.

query GetMetadataFiles($owner: String!, $repo: String!) {
repository(owner: $owner, name: $repo) {
metadataTree: object(expression: "${branchName}:${workspacePath}/metadata") {
... on Tree {
entries {
name
object {
... on Blob {
text
}
}
}
}
}
}
}`, {
owner: overlayRepoOwner,
repo: overlayRepoName
});

const entries = metadataResponse.repository?.metadataTree?.entries;
if (!entries) {
return [];
}

/** @type {Array<{path: string, mode: string, content: string}>} */
const treeEntries = [];

for (const entry of entries) {
if (!entry.name.endsWith('.yaml') && !entry.name.endsWith('.yml')) continue;
if (!entry.object?.text) continue;

let content = entry.object.text;
const packageNameMatch = content.match(/^\s+packageName:\s*"?([^"\n]+)"?\s*$/m);

Check warning on line 185 in update-overlay/create-pr-if-necessary.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the "RegExp.exec()" method instead.

See more on https://sonarcloud.io/project/issues?id=redhat-developer_rhdh-plugin-export-utils&issues=AZzTsv1RULVembEs1laS&open=AZzTsv1RULVembEs1laS&pullRequest=116
if (!packageNameMatch) continue;

const packageName = packageNameMatch[1].trim();
const newVersion = pluginVersions[packageName];
if (!newVersion) continue;

let modified = false;

// Update spec.version
const versionRegex = /^(\s+version:\s*).+$/m;
const versionMatch = content.match(versionRegex);

Check warning on line 196 in update-overlay/create-pr-if-necessary.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the "RegExp.exec()" method instead.

See more on https://sonarcloud.io/project/issues?id=redhat-developer_rhdh-plugin-export-utils&issues=AZzTsv1RULVembEs1laV&open=AZzTsv1RULVembEs1laV&pullRequest=116
if (versionMatch && versionMatch[0].trim() !== `version: ${newVersion}`) {
content = content.replace(versionRegex, `$1${newVersion}`);
core.info(` Updated version to ${newVersion} in ${entry.name}`);
modified = true;
}

// Update spec.dynamicArtifact tag for oci://ghcr.io references
const artifactRegex = /^(\s+dynamicArtifact:\s*oci:\/\/ghcr\.io\/[^:]+:)[^\s!]+(![^\s]+)$/m;
const artifactMatch = content.match(artifactRegex);

Check warning on line 205 in update-overlay/create-pr-if-necessary.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the "RegExp.exec()" method instead.

See more on https://sonarcloud.io/project/issues?id=redhat-developer_rhdh-plugin-export-utils&issues=AZzTsv1RULVembEs1laX&open=AZzTsv1RULVembEs1laX&pullRequest=116
if (artifactMatch) {
const newTag = `bs_${backstageVersion}__${newVersion}`;
content = content.replace(artifactRegex, `$1${newTag}$2`);
core.info(` Updated dynamicArtifact tag in ${entry.name}`);
modified = true;
}

if (modified) {
treeEntries.push({
path: `${workspacePath}/metadata/${entry.name}`,
mode: '100644',
content,
});
}
}

if (treeEntries.length > 0) {
core.info(`Updated ${treeEntries.length} metadata file(s)`);
}

return treeEntries;
}

const workspaceCheck = await checkWorkspace(overlayRepoBranchName);
if (workspaceCheck.status === 'sourceEqual') {
core.info(
Expand Down Expand Up @@ -379,6 +471,11 @@
core.info(`Deleting the overridden \`backstage.json\` because it's out-of-sync (\`${workspaceCheck.backstageVersionOverride}\`) with the backstage version of the new source commit (\`${backstageVersion}\`)`);
}

// Update metadata files with current plugin versions
const metadataTreeEntries = await updateMetadataFiles(
prBranchExists ? targetPRBranchName : overlayRepoBranchName
);

/** @type { Parameters<typeof githubClient.git.createTree>[0] } */
const createTreeOptions = {
owner: overlayRepoOwner,
Expand All @@ -387,6 +484,7 @@
tree: [
{ path: `${workspacePath}/plugins-list.yaml`, mode: '100644', content: updatedPluginsYamlContent },
{ path: `${workspacePath}/source.json`, mode: '100644', content: newSourceJsonContent },
...metadataTreeEntries,
]
};
if (deleteBackstageJson) {
Expand Down