Skip to content

Commit 4edc902

Browse files
committed
Release notes for 26.7.0
New platform features. Discovered via Claude, using a generated script. This will later inform a skill. Note: It misses release note comments inside PR descriptions. Working on a fix.
1 parent 3aa7294 commit 4edc902

3 files changed

Lines changed: 340 additions & 0 deletions

File tree

modules/ROOT/pages/release-notes.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ The Stackable Data Platform consists of multiple operators that work together.
77
Periodically a platform release is made, including all components of the platform at a specific version.
88

99
// WARNING: Please keep the empty newlines, otherwise headings are broken.
10+
include::partial$release-notes/release-26.7.adoc[]
11+
1012
include::partial$release-notes/release-26.3.adoc[]
1113

1214
include::partial$release-notes/release-25.11.adoc[]
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// DRAFT release notes for SDP 26.7.0.
2+
// Sourced from stackabletech issues/PRs labelled (release/26.7.0 OR scheduled-for/26.7.0)
3+
// AND (release-note OR release-note/action-required). 13 issues + 29 PRs.
4+
// All `// TODO(verify)` markers must be resolved before this is merged/published.
5+
6+
== Release 26.7
7+
8+
=== 26.7.0
9+
10+
// TODO(verify): exact release date. Tracking issue #847 target was 2026-07-17, shifted ~10 days -> ~2026-07-27.
11+
Released on 2026-07-27.
12+
13+
// TODO(highlights): written last, once all sections below are agreed.
14+
// [TIP,caption=Release highlights]
15+
// ====
16+
// * Highlight 1
17+
// ====
18+
19+
// TODO(breaking): overview of breaking changes, written last. Candidates (action-required / chore!):
20+
// * Generic database connection (Druid field rename) - link:#druid-features-26_7_0
21+
// * Apache Airflow EXPERIMENTAL_FILE_* rename - link:#airflow-removals-26_7_0
22+
// * Apache Superset EXPERIMENTAL_FILE_* rename - link:#superset-removals-26_7_0
23+
// * Apache NiFi 1.x CRD fields removed - link:#nifi-removals-26_7_0
24+
// * Apache Spark application templates now namespaced - link:#spark-fixes-26_7_0
25+
// [WARNING,caption=Overview of breaking changes]
26+
// ====
27+
// ====
28+
29+
==== New platform features
30+
31+
===== General
32+
33+
====== Miscellaneous
34+
35+
* The SDP now provides a generic database connection mechanism, giving a consistent way to configure connections to external SQL databases across operators.
36+
It has been rolled out to the Apache Airflow (https://github.com/stackabletech/airflow-operator/pull/754[airflow-operator#754]), Apache Hive (https://github.com/stackabletech/hive-operator/pull/674[hive-operator#674]) and Apache Superset (https://github.com/stackabletech/superset-operator/pull/722[superset-operator#722]) operators, and underpins new database connector support in Apache Druid and Trino (see the respective sections below).
37+
+
38+
--
39+
[WARNING]
40+
====
41+
*Breaking:* In the Stackable operator for Apache Druid the field `metadata_storage_database` has been renamed to `metadata_database`.
42+
====
43+
44+
// TODO(verify): xref to the generic database connection concept/usage docs once the page exists.
45+
Tracked in https://github.com/stackabletech/issues/issues/238[issues#238].
46+
--
47+
* Operators that support OIDC authentication can now configure the `clientAuthenticationMethod`.
48+
This resolves the Apache Druid OIDC issue where a provider advertising `private_key_jwt` could cause authentication to fail (a known issue in the 26.3 release).
49+
// TODO(verify): confirm which operators expose this field and add the relevant xref.
50+
Tracked in https://github.com/stackabletech/issues/issues/838[issues#838].
51+
* Operators can now resolve product images from registries other than `oci.stackable.tech`, making it possible to install the SDP from a mirror or private registry.
52+
// TODO(verify): confirm this landed for 26.7.0 (issue #716 is a tracking epic) and add the xref to the image-registry docs.
53+
Tracked in https://github.com/stackabletech/issues/issues/716[issues#716].
54+
55+
===== Apache Airflow
56+
57+
Apache Airflow can now authenticate git-sync against a repository using a custom CA, adding first-class support for CAs alongside the existing SSH and basic-auth options.
58+
// TODO(verify): xref to the DAG mounting / git-sync usage guide.
59+
Implemented in https://github.com/stackabletech/airflow-operator/pull/750[airflow-operator#750].
60+
61+
===== Apache NiFi
62+
63+
Apache NiFi can now authenticate git-sync against a repository using a custom CA, adding first-class support for CAs.
64+
// TODO(verify): xref to the NiFi git-sync usage guide.
65+
Implemented in https://github.com/stackabletech/nifi-operator/pull/903[nifi-operator#903].
66+
67+
===== Apache Superset
68+
69+
Two new roles, `worker` and `beat` (limited to a single replica), have been added so that Celery workers and the Celery beat scheduler can be enabled.
70+
// TODO(verify): the results backend currently supports Redis only (no S3); confirm whether to call this out. xref to Superset usage guide.
71+
Implemented in https://github.com/stackabletech/superset-operator/pull/724[superset-operator#724].
72+
73+
===== Open Policy Agent
74+
75+
The OPA operator now supports typed `configOverrides` for OPA's `config.json`, via JSON merge patch, JSON patches or a full file replacement.
76+
// TODO(verify): xref to the OPA configuration overrides docs.
77+
Implemented in https://github.com/stackabletech/opa-operator/pull/818[opa-operator#818].
78+
79+
===== OpenSearch
80+
81+
* Security configuration files are now hot-reloaded when changed, so that settings managed by the operator are applied without Pod restarts.
82+
// TODO(verify): xref to the OpenSearch security docs.
83+
Implemented in https://github.com/stackabletech/opensearch-operator/pull/130[opensearch-operator#130].
84+
* The operator now writes the actual node FQDNs into `plugins.security.nodes_dn` instead of a generic subject DN.
85+
// TODO(verify): confirm feature vs fix categorisation for opensearch-operator#144.
86+
Implemented in https://github.com/stackabletech/opensearch-operator/pull/144[opensearch-operator#144].
87+
88+
===== Trino
89+
90+
* Trino now supports the PostgreSQL connector, allowing PostgreSQL databases to be queried as a Trino catalog.
91+
// TODO(verify): xref to the Trino PostgreSQL connector docs.
92+
Implemented in https://github.com/stackabletech/trino-operator/pull/883[trino-operator#883].
93+
* A new `.spec.name.inferred.replaceHyphensWithUnderscores` field on `TrinoCatalog` allows tweaking the catalog name in Trino by replacing `-` with `_`.
94+
This lets you use valid Kubernetes resource names while keeping the convenience of `_` in catalog names.
95+
Implemented in https://github.com/stackabletech/trino-operator/pull/903[trino-operator#903].
96+
97+
===== Stackable commons-operator
98+
99+
The commons-operator restart-controller can now be told to ignore specific ConfigMaps and Secrets.
100+
Set the `restarter.stackable.tech/ignore` label on a ConfigMap or Secret, or the `restarter.stackable.tech/ignore-configmap.x` / `restarter.stackable.tech/ignore-secret.x` annotations on a StatefulSet, to exclude them from triggering restarts.
101+
// TODO(verify): xref to the restarter docs.
102+
Implemented in https://github.com/stackabletech/commons-operator/pull/410[commons-operator#410].
103+
104+
===== Stackable secret-operator
105+
106+
* The name of the CA certificate entry written by a `TrustStore` is now configurable, so it can be aligned with what consumers such as OpenShift expect (`tls.crt` vs `ca.crt`).
107+
// TODO(verify): xref to the TrustStore docs.
108+
Implemented in https://github.com/stackabletech/secret-operator/pull/679[secret-operator#679].
109+
* Domain components (DCs) can now be added to the subject DN of TLS certificates via the `secrets.stackable.tech/backend.autotls.cert.domain-components-in-subject-dn` volume annotation.
110+
// TODO(verify): xref to the secret-operator volume docs.
111+
Implemented in https://github.com/stackabletech/secret-operator/pull/708[secret-operator#708].
112+
113+
// TODO(verify): stackablectl#187 (uninstall Stacks and Demos) - stackablectl is versioned separately; confirm whether it belongs in these platform release notes.
114+
115+
// ============================================================================
116+
// TODO: remaining sections (next review rounds) - stubbed to keep the include valid.
117+
// ============================================================================
118+
119+
==== Platform improvements
120+
121+
// TODO: NiFi startup times (nifi#953), OPA DaemonSet maxSurge (opa#819),
122+
// typed OpenSearch configOverrides (opensearch#137), General > Vulnerabilities (CVE counts TODO).
123+
124+
==== Platform fixes
125+
126+
// TODO: internal-secret mutability (issues#843; airflow#770, trino#876),
127+
// SecretClasses requiring client cert regression (issues#547),
128+
// Spark connect user args (spark#696), Spark graceful SIGTERM shutdown (docker-images#1564),
129+
// Spark application templates namespaced (spark#694/#720 - BREAKING).
130+
131+
==== Platform deprecations
132+
133+
// TODO: product version deprecations (from docker-images version issues).
134+
135+
==== Platform removals
136+
137+
// TODO: NiFi 1.x CRD fields (nifi#960 - BREAKING), Airflow/Superset EXPERIMENTAL_FILE_* rename
138+
// (airflow#777, superset#721 - BREAKING), removed product versions.
139+
140+
==== Supported versions
141+
142+
// TODO(UNVERIFIED - reconcile against portal.stackable.build screenshot before publishing):
143+
// product versions (new/LTS/deprecated/removed), Kubernetes versions, OpenShift versions.
144+
145+
==== Upgrade from 26.3
146+
147+
// TODO: stackablectl + Helm uninstall/install for 26.3 -> 26.7, plus product-specific upgrade notes.
148+
149+
[#known-issues-26_7_0]
150+
==== Known issues
151+
152+
// TODO(verify): none known yet.

scripts/gather-release-notes.sh

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Gather the GitHub issues and pull requests that feed the release notes for a
5+
# given SDP release, straight from the stackabletech org.
6+
#
7+
# It searches for items carrying BOTH:
8+
# - a release label: release/<major.minor.patch> OR scheduled-for/<major.minor.patch>
9+
# - a release-note label: release-note OR release-note/action-required
10+
#
11+
# and prints a report grouped by repository, including the "Release notes"
12+
# snippet from each item body (the section the authors write in the PR template).
13+
#
14+
# It also flags two things that need human attention before a release:
15+
# - items still labelled `scheduled-for/<version>` (merged PRs should be
16+
# re-labelled `release/<version>`; open ones need to land or be dropped).
17+
# - open / unmerged PRs in the set.
18+
#
19+
# Counts are the ground truth from pagination, NOT the GitHub search
20+
# `total_count` (the web UI and that field can be misleading).
21+
#
22+
# Requires: gh (authenticated), jq.
23+
#
24+
# Usage:
25+
# scripts/gather-release-notes.sh -v <major.minor.patch> [--json]
26+
#
27+
# -v, --version Required. e.g. 26.7.0
28+
# --json Dump the raw combined JSON (all items) instead of the report.
29+
#
30+
# Examples:
31+
# scripts/gather-release-notes.sh -v 26.7.0
32+
# scripts/gather-release-notes.sh -v 26.7.0 --json > items.json
33+
34+
# ------------------------------
35+
# Args parsing
36+
# ------------------------------
37+
38+
VERSION=""
39+
OUTPUT="report"
40+
41+
while [[ "$#" -gt 0 ]]; do
42+
case $1 in
43+
-v|--version) VERSION="$2"; shift ;;
44+
--json) OUTPUT="json" ;;
45+
-h|--help) sed -n '3,30p' "$0"; exit 0 ;;
46+
*) echo "Unknown parameter passed: $1" >&2; exit 1 ;;
47+
esac
48+
shift
49+
done
50+
51+
if [ -z "$VERSION" ]; then
52+
echo "Usage: gather-release-notes.sh -v <major.minor.patch> [--json]" >&2
53+
exit 1
54+
fi
55+
56+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
57+
echo "Invalid version format. Please use the major.minor.patch format (e.g. 26.7.0)." >&2
58+
exit 1
59+
fi
60+
61+
for tool in gh jq; do
62+
if ! command -v "$tool" >/dev/null 2>&1; then
63+
echo "Required tool '$tool' not found on PATH." >&2
64+
exit 1
65+
fi
66+
done
67+
68+
# Minor version, e.g. 26.7 from 26.7.0
69+
MINOR=$(echo "$VERSION" | cut -d. -f1,2)
70+
71+
RELEASE_LABEL="release/$VERSION"
72+
SCHEDULED_LABEL="scheduled-for/$VERSION"
73+
QUERY="org:stackabletech label:$SCHEDULED_LABEL,$RELEASE_LABEL label:release-note,release-note/action-required"
74+
75+
# ------------------------------
76+
# Fetch (single paginated search; the search API already returns bodies)
77+
# ------------------------------
78+
79+
ITEMS_FILE=$(mktemp)
80+
trap 'rm -f "$ITEMS_FILE"' EXIT
81+
82+
# --paginate over search returns one JSON object per page; slurp the .items
83+
# arrays together and de-duplicate by html_url (defensive against overlap).
84+
gh api -X GET search/issues --paginate -f q="$QUERY" --jq '.items[]' \
85+
| jq -s 'unique_by(.html_url)' > "$ITEMS_FILE"
86+
87+
if [ "$OUTPUT" = "json" ]; then
88+
cat "$ITEMS_FILE"
89+
exit 0
90+
fi
91+
92+
# ------------------------------
93+
# Helper: is this item an action-required one?
94+
# ------------------------------
95+
is_action_required() { echo "$1" | jq -e 'any(.labels[].name; . == "release-note/action-required")' >/dev/null; }
96+
97+
# ------------------------------
98+
# Counts (ground truth = number of items actually returned)
99+
# ------------------------------
100+
TOTAL=$(jq 'length' "$ITEMS_FILE")
101+
N_ISSUES=$(jq '[.[] | select(.pull_request == null)] | length' "$ITEMS_FILE")
102+
N_PRS=$(jq '[.[] | select(.pull_request != null)] | length' "$ITEMS_FILE")
103+
104+
echo "# Release-notes source data for $VERSION (minor: $MINOR)"
105+
echo "#"
106+
echo "# Query: (label:$SCHEDULED_LABEL OR label:$RELEASE_LABEL)"
107+
echo "# AND (label:release-note OR label:release-note/action-required)"
108+
echo
109+
echo "## Counts (ground truth via pagination, not search total_count)"
110+
echo " Issues: $N_ISSUES"
111+
echo " PRs: $N_PRS"
112+
echo " Total: $TOTAL"
113+
echo
114+
115+
# ------------------------------
116+
# Hygiene flags
117+
# ------------------------------
118+
echo "## Hygiene flags"
119+
echo
120+
echo "### Items still labelled '$SCHEDULED_LABEL'"
121+
echo "# (merged PRs should be re-labelled '$RELEASE_LABEL'; open ones must land or be dropped)"
122+
SCHEDULED=$(jq -r --arg L "$SCHEDULED_LABEL" '
123+
[.[] | select(any(.labels[].name; . == $L))]
124+
| if length == 0 then " (none)" else
125+
.[] | " \(.repository_url | sub(".*/repos/stackabletech/";"")) #\(.number) [" +
126+
(if .pull_request == null then "issue"
127+
elif .pull_request.merged_at != null then "PR-MERGED"
128+
else "PR-OPEN" end) + "] \(.title)"
129+
end' "$ITEMS_FILE")
130+
echo "$SCHEDULED"
131+
echo
132+
echo "### Open / unmerged PRs in the set (resolve before release)"
133+
OPEN_PRS=$(jq -r '
134+
[.[] | select(.pull_request != null and .state == "open")]
135+
| if length == 0 then " (none)" else
136+
.[] | " \(.repository_url | sub(".*/repos/stackabletech/";"")) #\(.number) \(.title)"
137+
end' "$ITEMS_FILE")
138+
echo "$OPEN_PRS"
139+
echo
140+
141+
# ------------------------------
142+
# Items grouped by repository, with release-note snippet
143+
# ------------------------------
144+
echo "## Items grouped by repository"
145+
146+
REPOS=$(jq -r '[.[] | .repository_url | sub(".*/repos/stackabletech/";"")] | unique | .[]' "$ITEMS_FILE")
147+
148+
while IFS= read -r repo; do
149+
[ -z "$repo" ] && continue
150+
echo
151+
echo "### $repo"
152+
# Iterate items for this repo (compact JSON per line)
153+
jq -c --arg R "$repo" '.[] | select((.repository_url | sub(".*/repos/stackabletech/";"")) == $R)' "$ITEMS_FILE" \
154+
| while IFS= read -r item; do
155+
number=$(echo "$item" | jq -r '.number')
156+
title=$(echo "$item" | jq -r '.title')
157+
url=$(echo "$item" | jq -r '.html_url')
158+
labels=$(echo "$item" | jq -r '[.labels[].name] | join(", ")')
159+
if echo "$item" | jq -e '.pull_request == null' >/dev/null; then
160+
kind="issue"
161+
elif echo "$item" | jq -e '.pull_request.merged_at != null' >/dev/null; then
162+
kind="PR-merged"
163+
else
164+
kind="PR-$(echo "$item" | jq -r '.state')"
165+
fi
166+
marker=""
167+
if is_action_required "$item"; then marker=" **ACTION-REQUIRED**"; fi
168+
169+
echo "- #$number [$kind]$marker $title"
170+
echo " $url"
171+
echo " labels: $labels"
172+
# Extract the "Release note(s)" section from the body, if present.
173+
snippet=$(echo "$item" | jq -r '.body // ""' | awk '
174+
BEGIN { grab=0 }
175+
/^#+[[:space:]]*[Rr]elease[[:space:]]*[Nn]ote/ { grab=1; next }
176+
grab && /^#+[[:space:]]/ { exit }
177+
grab { print }
178+
' | sed 's/^/ /' | sed '/^[[:space:]]*$/d')
179+
if [ -n "$snippet" ]; then
180+
echo " release-note snippet:"
181+
echo "$snippet"
182+
else
183+
echo " release-note snippet: (none found in body)"
184+
fi
185+
done
186+
done <<< "$REPOS"

0 commit comments

Comments
 (0)