Skip to content

Commit 26eeb40

Browse files
Merge remote-tracking branch 'upstream/main' into SOLR-17949-azure-blob-repository
2 parents baa0b76 + a19b724 commit 26eeb40

464 files changed

Lines changed: 8731 additions & 4460 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/renovate.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@
4949
"schedule": ["before 9am on the first day of the month"]
5050
},
5151
{
52-
"description": "Google Cloud packages checked less often",
53-
"matchPackagePrefixes": ["com.google.cloud"],
54-
"groupName": "Google Cloud",
52+
"description": "Google Cloud BOM checked less often to avoid spam",
53+
"matchPackageNames": ["com.google.cloud:google-cloud-bom"],
5554
"schedule": ["before 9am on the first day of the month"]
5655
},
5756
{

.github/workflows/docker-nightly.yml

Lines changed: 31 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,73 +22,62 @@ jobs:
2222
include:
2323
# main branch - Gradle on JDK21, Docker images with JRE25
2424
- branch: main
25-
version: 11.0.0-SNAPSHOT
2625
gradle-jdk: 21
2726
dist: full
28-
base-image: eclipse-temurin:25-jre-jammy
27+
base-image: eclipse-temurin:25-jre-noble
2928
tag-suffix: ''
3029
- branch: main
31-
version: 11.0.0-SNAPSHOT
3230
gradle-jdk: 21
3331
dist: slim
34-
base-image: eclipse-temurin:25-jre-jammy
32+
base-image: eclipse-temurin:25-jre-noble
3533
tag-suffix: ''
3634

3735
# branch_10x - Gradle on JDK21, Docker images with JRE21 (default) and JRE25
3836
- branch: branch_10x
39-
version: 10.1.0-SNAPSHOT
4037
gradle-jdk: 21
4138
dist: full
42-
base-image: eclipse-temurin:21-jre-jammy
39+
base-image: eclipse-temurin:21-jre-noble
4340
tag-suffix: ''
4441
- branch: branch_10x
45-
version: 10.1.0-SNAPSHOT
4642
gradle-jdk: 21
4743
dist: slim
48-
base-image: eclipse-temurin:21-jre-jammy
44+
base-image: eclipse-temurin:21-jre-noble
4945
tag-suffix: ''
5046
- branch: branch_10x
51-
version: 10.1.0-SNAPSHOT
5247
gradle-jdk: 21
5348
dist: full
54-
base-image: eclipse-temurin:25-jre-jammy
49+
base-image: eclipse-temurin:25-jre-noble
5550
tag-suffix: '-java25'
5651

57-
# branch_10_0 - Gradle on JDK21, Docker images with JRE21 (default) and JRE25
58-
- branch: branch_10_0
59-
version: 10.0.0-SNAPSHOT
60-
gradle-jdk: 21
52+
# branch_9x - Gradle on JDK17, Docker images with JRE17 (default) and JRE21
53+
- branch: branch_9x
54+
gradle-jdk: 17
6155
dist: full
62-
base-image: eclipse-temurin:21-jre-jammy
56+
base-image: eclipse-temurin:17-jre-jammy
6357
tag-suffix: ''
64-
- branch: branch_10_0
65-
version: 10.0.0-SNAPSHOT
66-
gradle-jdk: 21
58+
- branch: branch_9x
59+
gradle-jdk: 17
6760
dist: slim
68-
base-image: eclipse-temurin:21-jre-jammy
61+
base-image: eclipse-temurin:17-jre-jammy
6962
tag-suffix: ''
70-
- branch: branch_10_0
71-
version: 10.0.0-SNAPSHOT
72-
gradle-jdk: 21
63+
- branch: branch_9x
64+
gradle-jdk: 17
7365
dist: full
74-
base-image: eclipse-temurin:25-jre-jammy
75-
tag-suffix: '-java25'
66+
base-image: eclipse-temurin:21-jre-jammy
67+
tag-suffix: '-java21'
7668

77-
# branch_9x - Gradle on JDK17, Docker images with JRE17 (default) and JRE21
78-
- branch: branch_9x
79-
version: 9.11.0-SNAPSHOT
69+
# branch_9_11 - Gradle on JDK17, Docker images with JRE17 (default) and JRE21
70+
- branch: branch_9_11
8071
gradle-jdk: 17
8172
dist: full
8273
base-image: eclipse-temurin:17-jre-jammy
8374
tag-suffix: ''
84-
- branch: branch_9x
85-
version: 9.11.0-SNAPSHOT
75+
- branch: branch_9_11
8676
gradle-jdk: 17
8777
dist: slim
8878
base-image: eclipse-temurin:17-jre-jammy
8979
tag-suffix: ''
90-
- branch: branch_9x
91-
version: 9.11.0-SNAPSHOT
80+
- branch: branch_9_11
9281
gradle-jdk: 17
9382
dist: full
9483
base-image: eclipse-temurin:21-jre-jammy
@@ -155,20 +144,21 @@ jobs:
155144
username: ${{ secrets.DOCKERHUB_USER }}
156145
password: ${{ secrets.DOCKERHUB_TOKEN }}
157146

158-
- name: Build Docker tag name
159-
id: tag
160-
run: |
161-
if [ "${{ matrix.dist }}" = "slim" ]; then
162-
echo "tag=${{ matrix.version }}-slim${{ matrix.tag-suffix }}" >> $GITHUB_OUTPUT
163-
else
164-
echo "tag=${{ matrix.version }}${{ matrix.tag-suffix }}" >> $GITHUB_OUTPUT
165-
fi
166-
167147
- name: Test and publish Docker image
168148
run: |
149+
TAG_ARGS=""
150+
if [ -n "${{ matrix.version }}" ]; then
151+
if [ "${{ matrix.dist }}" = "slim" ]; then
152+
TAG_ARGS="-Psolr.docker.imageTag=${{ matrix.version }}-slim${{ matrix.tag-suffix }}"
153+
else
154+
TAG_ARGS="-Psolr.docker.imageTag=${{ matrix.version }}${{ matrix.tag-suffix }}"
155+
fi
156+
elif [ -n "${{ matrix.tag-suffix }}" ]; then
157+
TAG_ARGS="-Psolr.docker.imageTagSuffix=${{ matrix.tag-suffix }}"
158+
fi
169159
./gradlew testDocker dockerPush \
170160
-Psolr.docker.imageRepo=apache/solr-nightly \
171-
-Psolr.docker.imageTag=${{ steps.tag.outputs.tag }} \
161+
$TAG_ARGS \
172162
-Psolr.docker.dist=${{ matrix.dist }} \
173163
-Psolr.docker.platform=linux/arm64,linux/amd64 \
174164
-Psolr.docker.baseImage=${{ matrix.base-image }}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Generate Renovate Changelog (Stage 1 - Prepare)
2+
3+
# Stage 1: runs with pull_request (no secrets, no write access).
4+
# Checks out BASE repo code only, runs the trusted Python script,
5+
# and saves the generated changelog file + PR metadata as an artifact
6+
# for Stage 2 to pick up and push to the fork branch.
7+
on:
8+
pull_request:
9+
types:
10+
- opened
11+
- synchronize
12+
branches:
13+
- main
14+
- 'branch_*'
15+
16+
concurrency:
17+
group: renovate-changelog-prepare-${{ github.event.pull_request.number }}
18+
cancel-in-progress: true
19+
20+
permissions:
21+
contents: read
22+
23+
jobs:
24+
generate:
25+
# Only run for Renovate bot PRs from the expected fork
26+
if: |
27+
github.event.pull_request.user.login == 'solrbot' &&
28+
github.event.pull_request.head.repo.full_name == 'solrbot/apache-_-solr'
29+
runs-on: ubuntu-latest
30+
31+
steps:
32+
- name: Checkout BASE repository at base branch (NOT fork code)
33+
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
34+
with:
35+
ref: ${{ github.event.pull_request.base.ref }}
36+
repository: ${{ github.repository }}
37+
38+
- name: Set up Python
39+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
40+
with:
41+
python-version: '3.x'
42+
43+
- name: Install dependencies
44+
run: python3 -m pip install --quiet pyyaml
45+
46+
- name: Generate changelog entry
47+
env:
48+
PR_NUMBER: ${{ github.event.pull_request.number }}
49+
PR_TITLE: ${{ github.event.pull_request.title }}
50+
run: |
51+
python3 .github/scripts/generate-renovate-changelog.py \
52+
--pr-number "$PR_NUMBER" \
53+
--pr-title "$PR_TITLE"
54+
55+
- name: Assemble artifact
56+
env:
57+
PR_NUMBER: ${{ github.event.pull_request.number }}
58+
HEAD_REF: ${{ github.event.pull_request.head.ref }}
59+
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
60+
run: |
61+
set -euo pipefail
62+
mkdir -p artifact
63+
if [ -d changelog/unreleased ]; then
64+
cp -r changelog/unreleased artifact/changelog-unreleased
65+
fi
66+
# Use printf + env vars to avoid shell injection from PR metadata values
67+
printf 'PR_NUMBER=%s\nHEAD_REF=%s\nHEAD_REPO=%s\n' \
68+
"$PR_NUMBER" "$HEAD_REF" "$HEAD_REPO" \
69+
> artifact/pr-metadata.env
70+
echo "Artifact contents:"; find artifact/ -type f
71+
72+
- name: Upload artifact
73+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
74+
with:
75+
name: renovate-changelog-artifact
76+
path: artifact/
77+
retention-days: 1
78+
if-no-files-found: error
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
name: Generate Renovate Changelog (Stage 2 - Push)
2+
3+
# Stage 2: runs after Stage 1 completes, in the base-repo context with access to
4+
# SOLRBOT_GITHUB_TOKEN. Downloads the pre-generated artifact (no fork code executed here),
5+
# validates metadata, and pushes the changelog file to the fork branch.
6+
on:
7+
workflow_run:
8+
workflows:
9+
- "Generate Renovate Changelog (Stage 1 - Prepare)"
10+
types:
11+
- completed
12+
13+
# Each Stage 2 run corresponds to a unique Stage 1 run (unique workflow_run.id).
14+
# No cancel-in-progress: Stage 1's concurrency already serializes per-PR.
15+
concurrency:
16+
group: renovate-changelog-push-${{ github.event.workflow_run.id }}
17+
18+
permissions:
19+
actions: read # Required to download artifacts from another workflow run
20+
contents: read # Minimal; actual write access to fork uses SOLRBOT_GITHUB_TOKEN PAT
21+
22+
jobs:
23+
push-changelog:
24+
# Only proceed if Stage 1 succeeded for the expected fork.
25+
# Checking head_repository here avoids a spurious artifact-not-found failure
26+
# when Stage 1 ran but skipped its generate job (e.g. non-solrbot PR).
27+
if: |
28+
github.event.workflow_run.conclusion == 'success' &&
29+
github.event.workflow_run.head_repository.full_name == 'solrbot/apache-_-solr'
30+
runs-on: ubuntu-latest
31+
32+
steps:
33+
- name: Download artifact from Stage 1
34+
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
35+
with:
36+
name: renovate-changelog-artifact
37+
run-id: ${{ github.event.workflow_run.id }}
38+
github-token: ${{ secrets.GITHUB_TOKEN }}
39+
path: downloaded-artifact/
40+
41+
- name: Read and validate PR metadata
42+
id: meta
43+
run: |
44+
set -euo pipefail
45+
META_FILE="downloaded-artifact/pr-metadata.env"
46+
if [ ! -f "$META_FILE" ]; then
47+
echo "::error::Metadata file missing from artifact"; exit 1
48+
fi
49+
50+
# Parse with grep/cut rather than source to avoid executing file content as shell.
51+
# Use || true so a missing key doesn't abort under set -euo pipefail before the
52+
# explicit emptiness check below can emit a meaningful error message.
53+
PR_NUMBER=$(grep '^PR_NUMBER=' "$META_FILE" | cut -d= -f2- || true)
54+
HEAD_REF=$(grep '^HEAD_REF=' "$META_FILE" | cut -d= -f2- || true)
55+
HEAD_REPO=$(grep '^HEAD_REPO=' "$META_FILE" | cut -d= -f2- || true)
56+
57+
if [ -z "$PR_NUMBER" ] || [ -z "$HEAD_REF" ] || [ -z "$HEAD_REPO" ]; then
58+
echo "::error::Missing required metadata fields (PR_NUMBER, HEAD_REF, or HEAD_REPO)"; exit 1
59+
fi
60+
61+
# Security: verify this is the expected fork before using SOLRBOT_GITHUB_TOKEN
62+
if [ "$HEAD_REPO" != "solrbot/apache-_-solr" ]; then
63+
echo "::error::Unexpected HEAD_REPO: '$HEAD_REPO'. Expected 'solrbot/apache-_-solr'. Aborting."; exit 1
64+
fi
65+
66+
# Validate PR_NUMBER is a plain positive integer (prevents injection)
67+
if ! [[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]]; then
68+
echo "::error::PR_NUMBER is not a valid positive integer: '$PR_NUMBER'"; exit 1
69+
fi
70+
71+
# Validate HEAD_REF using Git's own branch-name rules. This rejects edge cases
72+
# such as '..', '@{', trailing '.lock', and ':' (dangerous in push refspecs)
73+
# while still accepting valid Renovate branch names like renovate/node@lts.
74+
if ! git check-ref-format --branch "$HEAD_REF" > /dev/null 2>&1; then
75+
echo "::error::HEAD_REF is not a valid Git branch name: '$HEAD_REF'"; exit 1
76+
fi
77+
78+
echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
79+
echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT"
80+
echo "head_repo=$HEAD_REPO" >> "$GITHUB_OUTPUT"
81+
echo "Validated: PR#${PR_NUMBER} on ${HEAD_REPO}@${HEAD_REF}"
82+
83+
- name: Clone fork branch
84+
env:
85+
SOLRBOT_TOKEN: ${{ secrets.SOLRBOT_GITHUB_TOKEN }}
86+
HEAD_REPO: ${{ steps.meta.outputs.head_repo }}
87+
HEAD_REF: ${{ steps.meta.outputs.head_ref }}
88+
run: |
89+
set -euo pipefail
90+
# Store credentials so the token never appears in the command line or process list
91+
git config --global credential.helper store
92+
printf 'https://x-access-token:%s@github.com\n' "$SOLRBOT_TOKEN" > ~/.git-credentials
93+
chmod 600 ~/.git-credentials
94+
95+
git clone --depth=1 --branch "$HEAD_REF" \
96+
"https://github.com/${HEAD_REPO}.git" \
97+
fork-checkout
98+
99+
- name: Apply changelog to fork checkout
100+
id: apply
101+
env:
102+
PR_NUMBER: ${{ steps.meta.outputs.pr_number }}
103+
run: |
104+
set -euo pipefail
105+
CHANGELOG_DIR="fork-checkout/changelog/unreleased"
106+
ARTIFACT_DIR="downloaded-artifact/changelog-unreleased"
107+
108+
if [ ! -d "$CHANGELOG_DIR" ]; then
109+
echo "::error::changelog/unreleased not found in fork checkout"; exit 1
110+
fi
111+
112+
if [ ! -d "$ARTIFACT_DIR" ]; then
113+
echo "::warning::No changelog-unreleased directory in artifact for PR#${PR_NUMBER}"
114+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
115+
exit 0
116+
fi
117+
118+
# Remove stale PR#NNN-*.yml files (handles slug changes between synchronize events)
119+
find "$CHANGELOG_DIR" -maxdepth 1 -name "PR#${PR_NUMBER}-*.yml" -delete -print
120+
121+
# Copy the new PR#NNN-*.yml file(s) from the artifact
122+
COPIED=0
123+
for f in "${ARTIFACT_DIR}/PR#${PR_NUMBER}-"*.yml; do
124+
if [ -f "$f" ]; then
125+
cp -v "$f" "$CHANGELOG_DIR/"
126+
COPIED=$((COPIED + 1))
127+
fi
128+
done
129+
130+
if [ "$COPIED" -eq 0 ]; then
131+
echo "::warning::No PR#${PR_NUMBER}-*.yml file found in artifact"
132+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
133+
else
134+
echo "Copied $COPIED changelog file(s)"
135+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
136+
fi
137+
138+
- name: Commit and push to fork branch
139+
if: steps.apply.outputs.has_changes == 'true'
140+
env:
141+
HEAD_REF: ${{ steps.meta.outputs.head_ref }}
142+
PR_NUMBER: ${{ steps.meta.outputs.pr_number }}
143+
run: |
144+
set -euo pipefail
145+
cd fork-checkout
146+
147+
if [ -z "$(git status --porcelain changelog/unreleased/)" ]; then
148+
echo "No changelog changes (already up to date)"
149+
exit 0
150+
fi
151+
152+
git config user.name "SolrBot"
153+
git config user.email "solrbot@cominvent.com"
154+
155+
git add changelog/unreleased/
156+
git commit -m "Add changelog entry for PR#${PR_NUMBER}"
157+
158+
# Credential store (configured in Clone step) provides authentication
159+
git push origin "HEAD:refs/heads/${HEAD_REF}"
160+
161+
# Remove credentials from disk now that the push is complete
162+
rm -f ~/.git-credentials

0 commit comments

Comments
 (0)