Skip to content
Merged
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
143 changes: 143 additions & 0 deletions COMMIT_AND_RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# MySQLTuner Commit and Release Process Guide

This document describes the mandatory workflow for committing changes and releasing new versions of MySQLTuner. Following this process ensures quality, formatting consistency, version integrity, and metadata compliance.

---

## 🛠️ 1. Commit Process

Every contribution to MySQLTuner must pass through a strict formatting, code generation, testing, and commit linting pipeline before being pushed.

### Step 1.1: Development Branching
All changes (features, bug fixes, chore, etc.) MUST be done in a dedicated Git branch separated from `master`. Committing directly to the `master` branch is strictly prohibited.

### Step 1.2: Code Formatting
Ensure that `mysqltuner.pl` matches the project formatting standard:
```bash
make tidy
```
*Behind the scenes*: This formats the code with `perltidy` using the project's config [.perltidy](file:///.perltidy) and cleans up file line endings with `dos2unix`.

To check if the formatting is correct without modifying the file:
```bash
make check-tidy
```

### Step 1.3: Generate Required Assets
If your changes affect CLI options, documentation, vulnerability lists, or support metadata, run the appropriate generators before committing:
* **Documentation (USAGE.md)**: Rebuild the markdown usage guide from the Perl POD:
```bash
make generate_usage
```
* **Features List (FEATURES.md)**: Re-extract subroutines list:
```bash
make generate_features
```
* **CVE Vulnerabilities (vulnerabilities.csv)**: Fetch the latest security vulnerability definitions:
```bash
make generate_cve
```
* **End-of-Life Support Files (mysql_support.md, mariadb_support.md)**: Re-extract MySQL and MariaDB EOL dates:
```bash
make generate_eof_files
```
* **Current Version File (CURRENT_VERSION.txt)**: Keep the version file in sync:
```bash
make generate_version_file
```

### Step 1.4: Run Automated Tests
Validate your changes locally using both unit tests and multi-database lab testing:
1. **Unit & Regression Tests**:
```bash
make unit-tests
# or
prove -r tests/
```
2. **Laboratory Tests (Docker)**:
Ensure code executes correctly across multiple database versions (MySQL, MariaDB, Percona Server):
```bash
make test
# or run all environments
make test-all
```

### Step 1.5: Commit via Conventional Commits
All commits must follow the standard [Conventional Commits](https://www.conventionalcommits.org/) specification:
* **Allowed Types**: `feat`, `fix`, `chore`, `docs`, `perf`, `refactor`, `style`, `test`, `ci`
* **Format**: `<type>(<scope>): <short summary>` followed by optional body/footer.
* **Interactive Tool**: To guarantee compliance, commit using:
```bash
npm run commit
# or
git cz
```

### Step 1.6: Commit Hooks Enforcement
Husky enforces validation at commit time:
* **`pre-commit` Hook**: Automatically triggers `npm test` (`prove tests/*.t`). If unit tests fail, the commit is blocked.
* **`commit-msg` Hook**: Validates the commit message structure against Conventional Commit rules using `commitlint`.

---

## 🚀 2. Release Process

The release lifecycle is governed by automated pre-flight checks and note generators to guarantee stability and release integrity.

### Step 2.1: Open a Release Branch
Cut a release branch named after the target version (e.g., `v2.8.42`):
```bash
git checkout -b vX.XX.XX
```

### Step 2.2: Synchronize Version Numbers
Ensure the target version is synchronized across all of the following locations:
1. [CURRENT_VERSION.txt](file:///CURRENT_VERSION.txt)
2. [mysqltuner.pl](file:///mysqltuner.pl) header (`# mysqltuner.pl - Version X.XX.XX`)
3. [mysqltuner.pl](file:///mysqltuner.pl) internal variable (`our $tunerversion = "X.XX.XX"`)
4. [mysqltuner.pl](file:///mysqltuner.pl) POD Name (`MySQLTuner X.XX.XX - MySQL High Performance`)
5. [mysqltuner.pl](file:///mysqltuner.pl) POD Version (`Version X.XX.XX`)
6. [Changelog](file:///Changelog) latest version header line (`X.XX.XX YYYY-MM-DD`)

To update version strings automatically across the codebase, use one of:
```bash
make increment_sub_version # Bumps micro/sub version (e.g. 2.8.41 -> 2.8.42)
make increment_minor_version # Bumps minor version (e.g. 2.8.41 -> 2.9.0)
make increment_major_version # Bumps major version (e.g. 2.8.41 -> 3.0.0)
```

### Step 2.3: Update the Changelog & Generate Release Notes
1. Add detailed bullet points in [Changelog](file:///Changelog) under the new version header, categorized by Conventional Commit types (`chore`, `feat`, `fix`, `test`, `ci`, etc.).
2. Run the `/release-notes-gen` workflow (or script directly) to analyze the changelog, delta indicator metrics, and generate/update the corresponding release notes file:
```bash
python3 build/release_gen.py
```
*Behind the scenes*: This compiles the release summary, diagnostic growth statistics, commit differences, and CLI modifications into [releases/](file:///releases/) (e.g., `releases/v2.8.42.md`).

### Step 2.4: Execute Release Preflight Checks
Run the preflight checks to guarantee zero configuration mismatch and 100% compliance:
```bash
/release-preflight
```
*Behind the scenes*: This workflow:
1. Verifies version consistency across files (via [tests/version_consistency.t](file:///tests/version_consistency.t)).
2. Verifies that release notes exist in `releases/v[VERSION].md`.
3. Checks that all commit messages follow conventional commits since the last tag.
4. Checks project documentation formatting and metadata compliance.
5. Validates `mysqltuner.pl` code formatting (`make check-tidy`).
6. Runs the smoke test suite (`make test`).

### Step 2.5: Tag and Push (Unified Release Manager)
The final tag and push sequences are automated by the `/release-manager` workflow:
1. Verify you are on the release branch.
2. Commit all synchronized documentation and release notes.
3. Perform release tagging:
```bash
git tag -a vX.XX.XX -m "Release X.XX.XX" -m "Release notes contents..."
```
4. Push the branch and release tag:
```bash
git push origin vX.XX.XX
git push origin refs/tags/vX.XX.XX
```
5. Merge back into `master` and ensure tags are force pushed to origin to sync the workspace.
2 changes: 1 addition & 1 deletion CURRENT_VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.8.41
2.8.42
9 changes: 9 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# MySQLTuner Changelog

2.8.42 2026-05-25

- chore: bump version to 2.8.42.
- fix: resolve fake aborted connections count increase during password strength checks (#900).
- fix: resolve EOF metadata corruption and duplicated configurations in Emacs block (#904).
- ci: optimize release notes generation to isolate branch changes.
- perf: optimize --dumpdir performance by excluding heavy RDS/Aurora and internal metrics.

Comment on lines +3 to +10
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Date discrepancy in release metadata.

The Changelog entry is dated 2026-05-25, but the PR description states "Release 2.8.42 dated 2026-05-17". I've seen enough version-bump commits to know this usually means someone copy-pasted the wrong date somewhere.

Which date is the official release date? If it's 2026-05-25, the PR description should be updated. If it's 2026-05-17, this Changelog date and the corresponding releases/v2.8.42.md date need correction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Changelog` around lines 3 - 10, The Changelog entry for version 2.8.42 shows
date 2026-05-25 which conflicts with the PR description that says 2026-05-17;
confirm the authoritative release date and make a consistent change: if the
official release date is 2026-05-25, update the PR description to 2026-05-25; if
the official date is 2026-05-17, update the Changelog entry in "Changelog"
(version header for 2.8.42) to 2026-05-17 and also correct the date inside
releases/v2.8.42.md so both the Changelog and releases/v2.8.42.md match the
confirmed release date for version 2.8.42.


2.8.41 2026-05-17

- fix: filter MySQL CLI password warning from execute_system_command output.
Expand Down
2 changes: 2 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Features list for option: --feature (dev only)
---


* adjust_aborted_connects
* build_mysql_connection_command
* calculate_health_score
* cloud_setup
Expand Down Expand Up @@ -47,6 +48,7 @@ Features list for option: --feature (dev only)
* predictive_capacity_analysis
* process_sysbench_metrics
* push_recommendation
* save_aborted_connects_state
* security_recommendations
* setup_environment
* show_help
Expand Down
5 changes: 4 additions & 1 deletion MEMORY_DB.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MySQLTuner-perl Version Memory

## Current Version: 2.8.41
## Current Version: 2.8.42

## Project Evolution & Systemic Findings

Expand All @@ -18,6 +18,9 @@ Migrated several external commands to native Core Perl to reduce fork overhead a
- `uptime` -> `/proc/uptime` parsing or `$^T` calculation

### Recent Audits
- **v2.8.42**:
- Optimized `--dumpdir` analysis by skipping heavy views and AWS-specific metrics.
- Fixed fake aborted connections count increase when performing password strength checks (#900).
- **v2.8.41**:
- Completed project-wide refactoring to use standard Perl Boolean practices.
- Restored Debian maintenance account automatic login functionality (#896).
Expand Down
11 changes: 10 additions & 1 deletion POTENTIAL_ISSUES
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ The following external commands are currently used via `execute_system_command`
- [x] **Unit Tests Stability**: 100% pass (53 files, 262 tests).
- [x] **Regression Cleanliness**: No new `uninitialized value` or `Syntax error` found in Standard, Dumpdir, or Schemadir scenarios.

## [2026-04-13 Audit] Development v2.8.41
## [2026-05-17 Audit] Development v2.8.41

### [v2.8.41] Laboratory Verification

Expand All @@ -167,3 +167,12 @@ The following external commands are currently used via `execute_system_command`
- [x] **SQL Execution Failure**: Discovered during audit.
- Found in: `examples/20260429_112608_mysql96/Container/execution.log` (Line 10 and 12).
- Fix: MySQL 9.x `mysql` client removed support for `\G` and `\s` in batch mode (`-e`). Replaced `\G` with `-E` flag natively in `select_array` and `select_one_g`. Skipped error prints for `\s` if it fails natively.

## [2026-05-25 Audit] Development v2.8.42

### [v2.8.42] Laboratory Verification

- [x] **Unit Tests Stability**: 100% pass (54 files, 265 tests).
- [x] **Aborted Connections Counter Fix**: Verified via unit tests (`tests/test_issue_900.t`) that the fake aborted connections increase during password strength checking is successfully prevented.
- [x] **Dumpdir Exclusions**: Verified that heavy tables/views are successfully skipped to avoid query timeouts.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[!["Buy Us A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/jmrenouard)

[![Project Status](https://opensource.box.com/badges/active.svg)](https://opensource.box.com/badges)
[![MySQLTuner Version](https://img.shields.io/badge/version-2.8.41-blue.svg)](https://github.com/jmrenouard/MySQLTuner-perl/releases/tag/v2.8.41)
[![MySQLTuner Version](https://img.shields.io/badge/version-2.8.42-blue.svg)](https://github.com/jmrenouard/MySQLTuner-perl/releases/tag/v2.8.42)
[![Test Status](https://github.com/anuraghazra/github-readme-stats/workflows/Test/badge.svg)](https://github.com/anuraghazra/github-readme-stats/)
[![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/jmrenouard/MySQLTuner-perl.svg)](https://isitmaintained.com/project/jmrenouard/MySQLTuner-perl "Average time to resolve an issue")
[![Percentage of open issues](https://isitmaintained.com/badge/open/jmrenouard/MySQLTuner-perl.svg)](https://isitmaintained.com/project/jmrenouard/MySQLTuner-perl "Percentage of issues still open")
Expand Down
16 changes: 16 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,15 @@ To ensure consistency and high-density development, the following roles are defi
* [x] **Cluster & Replication Intelligence**:
* [x] Root cause analysis for replication lag (IO/SQL thread contention).
* [ ] GTID consistency checks and multi-source replication tuning.
* [x] **Consolidated SQL Modeling & Naming Conventions**:
* [x] Consolidated Primary Key naming, surrogate keys, table singular naming, and table/column casing checks into single-line counters in General recommendations.
* [x] Implemented advanced dominant style detection and deviations audit for tables, views, indexes, and columns.
* [ ] **CSV Export Enhancements**:
* [ ] Export naming convention deviations (tables, views, indexes, columns), primary key naming/surrogate key issues, missing foreign keys, JSON columns without virtual columns, and insecure authentication plugins to separate CSV files.
* [/] **Security Hardening 2.0**:
* [ ] Version-based CVE exposure detection (community-fed database).
* [x] Advanced encryption-at-rest (TDE) and SSL/TLS cipher suite validation.
* [ ] **Extended Authentication Plugins Audit**: Verify password hashing methods against the extended plugins support matrix (including `mysql_native_password`, `mysql_old_password`, `sha256_password`, `caching_sha2_password`, `unix_socket`, `ed25519`, and the new MariaDB `parsec` plugin). See [AUTHENTICATION_PLUGINS.md](file:///documentation/AUTHENTICATION_PLUGINS.md).
* [/] **Guided Auto-Fix Engine**:
* [ ] Interactive mode to simulate configuration changes.
* [x] Generation of ready-to-use `SET GLOBAL` or `my.cnf` snippets.
Expand Down Expand Up @@ -183,6 +189,16 @@ To ensure consistency and high-density development, the following roles are defi
* [ ] **Compression & Efficiency**:
* [ ] **On-the-fly Compression**: Support for compressed `.gz` exports to minimize disk footprint in container/limited-storage environments.

## 🔮 Strategic Technical Evolutions

* [ ] Set up a pipeline to automatically audit and verify reference link availability inside the repository documentation to prevent dead links.
* [ ] Integrate standard documentation reference anchors dynamically within MySQLTuner CLI help screens and specific advisor output blocks.
* [ ] Support localized versions of the reference documentation matching other translations of the script (e.g. Italian, French, Russian).
* [ ] **Automated Changelog Formatting Verification**: Implement a Git pre-commit hook that automatically checks if the `Changelog` has been modified when changes of type `feat` or `fix` are detected, preventing commits without changelog documentation.
* [ ] **Containerized Validation Runners**: Standardize local pre-flight checks by executing all verification steps (including unit tests and version consistency checks) inside a standardized, minimal Docker environment to avoid environmental differences between developer environments and CI.
* [ ] **Interactive Release Orchestrator**: Create a script that automates the interactive selection of version bump categories (micro, minor, major), executes the version replacement across all 6 reference locations, and automatically runs the `release_gen.py` script to generate release notes in a single workflow step.


## 🤝 Contribution & Feedback

We welcome community feedback on this roadmap. If you have specific feature requests or want to contribute to a specific phase, please open an issue on our [GitHub repository](https://github.com/jmrenouard/MySQLTuner-perl).
4 changes: 2 additions & 2 deletions USAGE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NAME

MySQLTuner 2.8.41 - MySQL High Performance Tuning Script
MySQLTuner 2.8.42 - MySQL High Performance Tuning Script

# IMPORTANT USAGE GUIDELINES

Expand All @@ -15,7 +15,7 @@ See `mysqltuner --help` for a full list of available options and their categorie

# VERSION

Version 2.8.41
Version 2.8.42
&#x3d;head1 PERLDOC

You can find documentation for this module with the perldoc command.
Expand Down
35 changes: 32 additions & 3 deletions build/release_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,39 @@ def get_changelog_blocks():

def get_git_commits(version):
try:
# Check current branch
branch = subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'], stderr=subprocess.DEVNULL).decode().strip()

# Determine if we can compare with master
has_master = False
for ref in ['master', 'origin/master']:
try:
subprocess.check_call(['git', 'rev-parse', '--verify', ref], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
has_master = ref
break
except subprocess.CalledProcessError:
continue

if has_master and branch != 'master':
# We are on a branch, get commits between master (or origin/master) and HEAD
commits = subprocess.check_output(['git', 'log', f'{has_master}..HEAD', '--pretty=format:- %s (%h)']).decode().strip()
if commits:
return commits

tag = f"v{version}"
# Find the previous tag if it exists
try:
prev_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0', f'{tag}^'], stderr=subprocess.DEVNULL).decode().strip()
commits = subprocess.check_output(['git', 'log', f'{prev_tag}..{tag}', '--pretty=format:- %s (%h)']).decode().strip()
return commits if commits else "No new commits recorded."
except:
return "Initial release or no previous tag found."
# Maybe the tag doesn't exist yet, try HEAD instead of tag
try:
prev_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0'], stderr=subprocess.DEVNULL).decode().strip()
commits = subprocess.check_output(['git', 'log', f'{prev_tag}..HEAD', '--pretty=format:- %s (%h)']).decode().strip()
return commits if commits else "No new commits recorded."
except:
return "Initial release or no previous tag found."
except Exception:
return "Commit history unavailable."

Expand Down Expand Up @@ -91,13 +116,17 @@ def analyze_tech_details(version):

# Previous version code
try:
prev_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0', f'{tag}^'], stderr=subprocess.DEVNULL).decode().strip()
try:
prev_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0', f'{tag}^'], stderr=subprocess.DEVNULL).decode().strip()
except:
prev_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0'], stderr=subprocess.DEVNULL).decode().strip()

old_code = subprocess.check_output(['git', 'show', f'{prev_tag}:mysqltuner.pl']).decode()
old_opts = get_cli_options(old_code)
old_indicators = analyze_indicators(old_code)
old_names = extract_diagnostic_names(old_code)
except:
# Fallback to empty if no previous tag
# Fallback to empty if no previous tag at all
old_opts = set()
old_indicators = {'good':0, 'bad':0, 'info':0, 'total':0}
old_names = {'good': set(), 'bad': set(), 'info': set()}
Expand Down
15 changes: 15 additions & 0 deletions documentation/AUTHENTICATION_PLUGINS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# MySQL and MariaDB Authentication Plugins Reference

This document provides a comprehensive overview of authentication plugins across MySQL and MariaDB, including security levels, deprecation status, and platform support.

## Summary Table

| Plugin Name | Description | Algorithm | Security Level | Deprecated / Obsolete | Present in MySQL | Present in MariaDB |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| `mysql_native_password` | Historical default authentication method. | SHA-1 | Low | Yes (Removed from MySQL 8.4+ / Deprecated in MariaDB) | ✅ (Obsolete) | ✅ (Historical default) |
| `mysql_old_password` | Ancient pre-4.1 authentication method. | SHA-1 (Old) | Very Low | Yes (Removed) | ❌ | ✅ (Obsolete) |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What hashing algorithm does the MySQL/MariaDB mysql_old_password plugin use, and is it SHA-1 or a legacy pre-4.1 hash format?

💡 Result:

The mysql_old_password plugin uses a legacy, insecure pre-4.1 password hashing algorithm, not SHA-1 [1][2][3]. This algorithm produces a 16-byte hash value [1][4][5]. In contrast, the newer 4.1+ authentication method (mysql_native_password) utilizes a double-SHA-1 hashing process and produces a 41-byte hash value [1][4][6]. The mysql_old_password plugin and its associated pre-4.1 hashing method are considered obsolete and insecure [2][3][7]. Support for this plugin and the pre-4.1 hash format was removed in MySQL 5.7.5 [1][5]. While it remains available in some environments for backward compatibility, it is strongly recommended to migrate to more secure authentication plugins such as caching_sha2_password or ed25519 [2][8][9].

Citations:


Fix documentation: mysql_old_password is not SHA-1 (it’s pre-4.1 legacy hashing).
Line 10 labels mysql_old_password as SHA-1 (Old), but that plugin uses the legacy pre-4.1 password hashing algorithm (not SHA-1). Adjust the table wording to “legacy pre-4.1 hash” (and reserve “double-SHA-1” for mysql_native_password) so the security story isn’t told with the wrong algorithm.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@documentation/AUTHENTICATION_PLUGINS.md` at line 10, Update the documentation
row for the `mysql_old_password` entry in AUTHENTICATION_PLUGINS.md: change the
algorithm label from "SHA-1 (Old)" to "legacy pre-4.1 hash" and ensure
`mysql_native_password` keeps the "double-SHA-1" wording so the table accurately
distinguishes the legacy pre-4.1 hashing from the double-SHA-1 native method.

| `sha256_password` | Authenticates using SHA-256 with salting. | SHA-256 | High | Yes (Due to CPU scalability issues without TLS) | ❌ (Removed in 8.4) | ✅ |
| `caching_sha2_password` | Optimized version of SHA-256 with memory caching. | SHA-256 | High | No | ✅ (Default since 8.0) | ✅ (Since v11.4 for compatibility) |
| `unix_socket` | Authentication via OS-level user identity (UID). | OS Identity | Very High | No | ✅ (as `auth_socket`) | ✅ |
| `ed25519` | Elliptic Curve digital signature algorithm (EdDSA). | Ed25519 | Very High | No | ❌ (Except via third-party Enterprise modules) | ✅ |
| `parsec` | Password Authentication using Response Signed with Elliptic Curve (new MariaDB standard). | PBKDF2 + SHA-512 + Ed25519 | Maximal | No | ❌ | ✅ |
Loading