Skip to content

IGNITE-28989 update log4j dependency #3072

IGNITE-28989 update log4j dependency

IGNITE-28989 update log4j dependency #3072

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
name: Protected Classes
# pull_request_target for the write token needed to comment/label the PR. The fork's changes are
# read through the API as data and never checked out or executed, so no allow-unsafe-pr-checkout and
# no working copy of the PR code on the runner. Do not add a step that builds or runs the PR code.
on: pull_request_target
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
check-protected-classes:
runs-on: ubuntu-latest
name: Rolling Upgrade check
permissions:
issues: write
pull-requests: write
checks: write
steps:
- name: Detect protected class changes and report
uses: actions/github-script@v8
with:
script: |
const ANNOTATION = 'org.apache.ignite.internal.Order';
const MARKER = '<!-- ignite-rolling-upgrade-check -->';
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const baseSha = pr.base.sha;
const headSha = pr.head.sha;
// Changed files are read from the API as data; the fork's code is never checked out or executed.
const files = await github.paginate(github.rest.pulls.listFiles, {
owner, repo, pull_number: pr.number, per_page: 100,
});
// Reproduce `git diff --no-renames --diff-filter=ADM`: a rename is a delete(old)+add(new) pair.
// A protected class carries the @Order annotation; an added file is defined by the head revision,
// a deleted/modified one by the base.
const revisions = [];
for (const f of files) {
if (f.status === 'added' || f.status === 'copied')
revisions.push([f.filename, headSha]);
else if (f.status === 'removed' || f.status === 'modified' || f.status === 'changed')
revisions.push([f.filename, baseSha]);
else if (f.status === 'renamed') {
revisions.push([f.previous_filename, baseSha]);
revisions.push([f.filename, headSha]);
}
}
const isProtected = async (path, ref) => {
let meta;
try {
({ data: meta } = await github.rest.repos.getContent({ owner, repo, path, ref }));
} catch (e) {
if (e.status === 404) return false;
throw e;
}
if (Array.isArray(meta) || meta.type !== 'file') return false;
let content = meta.content ? Buffer.from(meta.content, 'base64').toString('utf8') : '';
if (!content && meta.sha) {
const { data: blob } = await github.rest.git.getBlob({ owner, repo, file_sha: meta.sha });
content = Buffer.from(blob.content, blob.encoding).toString('utf8');
}
return content.includes(ANNOTATION);
};
const hits = [];
for (const [path, ref] of revisions) {
if (path.endsWith('.java') && await isProtected(path, ref)) hits.push(path);
}
if (hits.length === 0) return;
// File names come from the fork; render them as inert inline code so they cannot inject
// markdown (backticks, @mentions, links) into content posted under the bot's write token.
const safe = f => '`' + String(f).replace(/[`\r\n]/g, '') + '`';
const list = hits.map(f => '- ' + safe(f)).join('\n');
const summary = [
'This PR modifies protected classes (with **Order** annotation).',
'Changes to these classes can break rolling upgrade compatibility.',
'',
'**Affected files:**',
list,
].join('\n');
const body = MARKER + '\n## Possible compatibility issues. Please, check rolling upgrade cases\n\n' + summary + '\n';
const comments = await github.paginate(github.rest.issues.listComments, {
owner, repo, issue_number: pr.number,
});
const existing = comments.find(c => c.body.includes(MARKER));
if (existing) {
await github.rest.issues.deleteComment({ owner, repo, comment_id: existing.id });
}
await github.rest.issues.createComment({ owner, repo, issue_number: pr.number, body });
await github.rest.issues.addLabels({
owner, repo, issue_number: pr.number, labels: ['compatibility'],
});
await github.rest.checks.create({
owner, repo,
name: 'Rolling upgrade compatibility',
head_sha: headSha,
status: 'completed',
conclusion: 'neutral',
output: { title: 'Possible compatibility issues', summary },
});