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
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -233,14 +233,17 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.sha }}
ref: refs/tags/v1.0.0-rc.1
- uses: ./.github/actions/setup-php-composer
with:
php-version: "8.4"
- name: Verify the exact committed artifact
- name: Verify the immutable RC artifact
env:
ARTIFACT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
run: composer release:verify -- --target=1.0.0-rc.1 --sha="$ARTIFACT_SHA"
ARTIFACT_SHA: 34c3b874525d36ae064c162cdd553bc75d18772b
run: |
set -euo pipefail
test "$(git rev-parse HEAD)" = "$ARTIFACT_SHA"
composer release:verify -- --target=1.0.0-rc.1 --sha="$ARTIFACT_SHA"

exploratory:
name: Exploratory MySQL Innovation (not required)
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ All notable changes to this project are documented in this file.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [Semantic Versioning](https://semver.org/).

## [1.0.0-rc.1]
## [1.0.0-rc.1] - 2026-11-12

First release candidate target. Publication state recorded during preparation: **Unpublished**.
First release candidate, published on [Packagist](https://packagist.org/packages/maatify/php-persistence).

### Added

Expand All @@ -20,3 +20,5 @@ First release candidate target. Publication state recorded during preparation: *
- Composer manifest, PHPStan at level `max`, PER-CS 3.1 code-style verification, and a real MySQL/MariaDB Integration test infrastructure (`scripts/integration.php`, `compose.integration.yaml`, `docker/integration-matrix.json`).

No database version range is declared as supported; see [PHP_PERSISTENCE_PACKAGE_REFERENCE.md §8](PHP_PERSISTENCE_PACKAGE_REFERENCE.md#8-database-engine-support). Durable decisions governing the changes above are indexed in [docs/decisions/DECISIONS_INDEX.md](docs/decisions/DECISIONS_INDEX.md).

[1.0.0-rc.1]: https://github.com/Maatify-ltd/php-persistence/releases/tag/v1.0.0-rc.1
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ composer test:regression # no Docker needed
composer test:integration # needs Docker; starts a disposable MySQL/MariaDB service
composer examples:smoke # needs Docker; smoke-executes examples/ against a real engine
composer test:consumer # needs Docker; two fresh external Composer verification runs
composer release:verify -- --target=1.0.0-rc.1 --sha="$(git rev-parse HEAD)"
composer release:verify -- --target=1.0.0-rc.1 --sha=34c3b874525d36ae064c162cdd553bc75d18772b
actionlint .github/workflows/*.yml
```

Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
<img alt="Maatify.dev" src="https://www.maatify.dev/company-profile/maatify_logo_dark.svg">
</picture>

[![Status at preparation](https://img.shields.io/badge/Status%20at%20preparation-Development-blue)](README.md#overview)
[![Status](https://img.shields.io/badge/Status-Release%20Candidate-blue)](https://github.com/Maatify-ltd/php-persistence/releases/tag/v1.0.0-rc.1)
[![Version](https://img.shields.io/badge/Version-1.0.0--rc.1-blue)](https://packagist.org/packages/maatify/php-persistence)
[![PHP](https://img.shields.io/badge/PHP-%5E8.4-8892BF)](composer.json)
[![License](https://img.shields.io/badge/License-Proprietary-green)](LICENSE)
[![PHPStan](https://img.shields.io/badge/PHPStan-Level%20Max-brightgreen)](README.md#quality-status)

[![Registry](https://img.shields.io/badge/Registry-Packagist-F28D1A)](https://packagist.org/packages/maatify/php-persistence)
[![Monthly downloads](https://img.shields.io/packagist/dm/maatify/php-persistence)](https://packagist.org/packages/maatify/php-persistence/stats)
[![Total downloads](https://img.shields.io/packagist/dt/maatify/php-persistence)](https://packagist.org/packages/maatify/php-persistence/stats)
[![Maatify Ecosystem](https://img.shields.io/badge/Maatify-Ecosystem-blueviolet)](https://github.com/Maatify)

[![Usage Guide](https://img.shields.io/badge/Docs-Usage_Guide-blue)](docs/guides/USAGE_GUIDE.md)
Expand All @@ -32,7 +36,7 @@ Direct-PDO Transaction, Pagination, and Ordering utilities for MySQL and MariaDB

`maatify/php-persistence` is a small, direct-PDO toolkit with three independent capabilities over a **caller-supplied** `PDO` connection: running callbacks inside a transaction or a caller's savepoint (with optional bounded deadlock replay), parameterized whitelist-sorted bounded pagination, and locking next-position/move operations for integer display-order columns. It is developed as a separate package from the earlier, published `maatify/persistence` ([coexistence rules](docs/decisions/DEC-005-coexistence-with-legacy-package.md)), not a drop-in replacement.

This tree is prepared as the **Release Candidate artifact `1.0.0-rc.1`**. Its **publication state at qualification** is **Unpublished**.
**Release Candidate `1.0.0-rc.1`** is published on [Packagist](https://packagist.org/packages/maatify/php-persistence) and available as a [GitHub pre-release](https://github.com/Maatify-ltd/php-persistence/releases/tag/v1.0.0-rc.1). The package has no Stable release.

## Key Features

Expand All @@ -53,13 +57,13 @@ These are declared runtime requirements, not a statement that any specific datab

## Installation

The exact Composer installation target for this artifact is:
Install the exact release candidate from Packagist:

```bash
composer require maatify/php-persistence:1.0.0-rc.1
```

This command resolves through the approved Composer distribution source only after that exact version is published. See the [target changelog](CHANGELOG.md#100-rc1) and [security policy](SECURITY.md) for lifecycle and support details.
See the [changelog](CHANGELOG.md) and [security policy](SECURITY.md) for release and support details.

## Usage

Expand Down
6 changes: 3 additions & 3 deletions docs/guides/RELEASE_ARTIFACT_VERIFICATION.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Release Artifact Verification

The preparation target for this tree is `maatify/php-persistence:1.0.0-rc.1`. Its publication state during preparation is Unpublished.
The release target covered here is `maatify/php-persistence:1.0.0-rc.1`. Its immutable artifact is available at `v1.0.0-rc.1`.

Run the same archive checks as CI from a checkout containing the exact committed candidate. The command needs Git, tar, PHP and Composer.

```sh
composer release:verify -- --target=1.0.0-rc.1 --sha="$(git rev-parse HEAD)"
composer release:verify -- --target=1.0.0-rc.1 --sha=34c3b874525d36ae064c162cdd553bc75d18772b
```

The verifier creates an isolated checkout of the selected commit. It generates a VCS archive with `git archive` and a Composer archive with `composer archive`, independently of each other. The verification checks the actual entries and bytes, including required consumer files, the full runtime source, manifest identity and production PSR-4 mapping, and repository-only or sensitive paths. The log records the target, commit, tree, and a file inventory and SHA-256 for each generated archive. The temporary workspace is removed when verification ends. The sensitive-path and private-key checks are structural. The Lead reviews release claims, changelog allocation and the contents for sensitive data in context.

In pull-request CI the archive job checks out and verifies the exact PR HEAD. On a push it verifies the exact pushed commit. Qualification requires Full Applicable CI and Release Artifact Verification on the same actual, Owner-authorized `main` commit and exact target. The [Consumer Verification Harness](CONSUMER_VERIFICATION.md) separately exercises runtime consumption.
Before publication, the archive job verified the exact PR HEAD or pushed SHA. The published RC archive job now checks out the tag and verifies it against its recorded qualified SHA. Other jobs continue to verify the changes on the PR or pushed commit. Qualification of a future target requires Full Applicable CI and Release Artifact Verification on the same actual, Owner-authorized `main` candidate commit for that target. The [Consumer Verification Harness](CONSUMER_VERIFICATION.md) separately exercises runtime consumption.

## Published Artifact Verification

Expand Down
7 changes: 4 additions & 3 deletions tests/Regression/IntegrationInfrastructureTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,14 @@ public function testGateInspectsEveryRequiredJob(): void
self::assertStringContainsString('echo "$RESULTS" | jq -e \'all(.[]; .result == "success")\' > /dev/null', $gate);
}

public function testReleaseArtifactGateVerifiesTheExactWorkflowSha(): void
public function testReleaseArtifactGateVerifiesTheQualifiedRcTag(): void
{
$workflow = self::read('.github/workflows/ci.yml');
[, $following] = array_pad(explode("\n release-artifact:\n", $workflow, 2), 2, '');
[$job] = explode("\n exploratory:\n", $following, 2);
self::assertStringContainsString('ref: ${{ github.event.pull_request.head.sha || github.sha }}', $job);
self::assertStringContainsString('ARTIFACT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}', $job);
self::assertStringContainsString('ref: refs/tags/v1.0.0-rc.1', $job);
self::assertStringContainsString('ARTIFACT_SHA: 34c3b874525d36ae064c162cdd553bc75d18772b', $job);
self::assertStringContainsString('test "$(git rev-parse HEAD)" = "$ARTIFACT_SHA"', $job);
self::assertStringContainsString('composer release:verify -- --target=1.0.0-rc.1 --sha="$ARTIFACT_SHA"', $job);
self::assertStringContainsString('persist-credentials: false', $job);
self::assertStringContainsString('"release:verify": "@php scripts/release-artifact.php"', self::read('composer.json'));
Expand Down