Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d0087ec
Features/float from native (#88)
Spomky Nov 13, 2025
2a5fb86
Remove readonly modifier from properties in various CBOR object class…
Spomky Nov 13, 2025
718641f
Merge pull request #91 from Spomky-Labs/3.2.x-merge-up-into-3.3.x_vcV…
Spomky Nov 13, 2025
daae301
Bump actions/upload-artifact from 4.6.2 to 5.0.0 (#94)
dependabot[bot] Nov 13, 2025
7f6bd33
Bump renovatebot/github-action from 41.0.3 to 44.0.2 (#93)
dependabot[bot] Nov 13, 2025
b705c99
Bump github/codeql-action from 3 to 4 (#92)
dependabot[bot] Nov 13, 2025
711ec0c
Bump actions/checkout from 4.2.2 to 5.0.0 (#95)
dependabot[bot] Nov 13, 2025
44c06e4
Refactor tag creation methods to return self and improve error handli…
Spomky Nov 13, 2025
4503cd6
Add comprehensive documentation for CBOR PHP library and update READM…
Spomky Nov 13, 2025
8d01b3c
Update CI badge in README for improved clarity
Spomky Nov 13, 2025
28c695b
Bump actions/checkout from 5.0.0 to 6.0.1 (#103)
dependabot[bot] Jan 3, 2026
1889f74
Bump renovatebot/github-action from 44.0.2 to 44.2.2 (#101)
dependabot[bot] Jan 3, 2026
501ac35
Bump actions/upload-artifact from 5.0.0 to 6.0.0 (#100)
dependabot[bot] Jan 3, 2026
d44e50d
Bump dessant/lock-threads from 5 to 6 (#99)
dependabot[bot] Jan 3, 2026
89ca375
Bump actions/cache from 4 to 5 (#102)
dependabot[bot] Jan 3, 2026
3749f6b
Bump renovatebot/github-action from 44.2.2 to 46.0.0 (#105)
dependabot[bot] Feb 23, 2026
ac6aed7
Bump actions/checkout from 6.0.1 to 6.0.2 (#104)
dependabot[bot] Feb 23, 2026
413962f
Bump renovatebot/github-action from 46.0.0 to 46.1.7 (#115)
dependabot[bot] Apr 1, 2026
0a4c301
Bump laminas/automatic-releases from 1.25.0 to 1.26.2 (#109)
dependabot[bot] Apr 1, 2026
61e91f8
Bump ramsey/composer-install from 3 to 4 (#114)
dependabot[bot] Apr 1, 2026
4e89de9
Bump actions/upload-artifact from 6.0.0 to 7.0.0 (#108)
dependabot[bot] Apr 1, 2026
b3ca084
Merge up 3.2.x into 3.3.x (#118)
Spomky Apr 1, 2026
fee1d13
Fix CI: ECS import ordering and exported files check (#120)
Spomky Apr 1, 2026
7bb518b
Merge remote-tracking branch 'origin/3.3.x' into 3.3.x-merge-up-into-…
Spomky Apr 1, 2026
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
194 changes: 194 additions & 0 deletions .agents/skills/merge-up/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
name: merge-up
description: >
Cascade-merge maintained branches from oldest to newest (e.g.
3.1.x → 3.2.x → 3.3.x → 4.0.x). Use when the user says "merge branches",
"merge up", "cascade merge", "sync branches", or "update branches".
---

# Branch Cascade Merge

Merges each maintained branch into the next one, from oldest to newest.

## Progress checklist

- [ ] Step 0: Pre-flight checks
- [ ] Step 1: Determine maintained branches and pull them
- [ ] Step 2: Cascade merge loop

---

## Confirmation rule

Whenever the skill says **"Wait for confirmation"**, treat anything other than an
explicit affirmative as **no**: stop and ask the user how they want to proceed.

---

## Step 0 — Pre-flight checks

```bash
git status --porcelain --untracked-files=no
```

If any output, **stop**:
> "The working tree is not clean. Please commit or stash your changes first."

---

## Step 1 — Determine maintained branches and pull them

### 1a. Get the branch list

Ask the user which branches to cascade-merge. The user should provide an
ordered list from oldest to newest (e.g. `3.1.x 3.2.x 3.3.x 4.0.x`).

If the user doesn't provide a list, determine it from remote branches:

```bash
git branch -r --list 'origin/*.*.x' | sed 's|origin/||' | sort -V
```

Present the list and **wait for confirmation** before proceeding. The user may
want to exclude some branches (e.g. EOL branches). Store the confirmed list as
`BRANCHES`.

### 1b. Pull every branch

For each branch in `BRANCHES`:

```bash
git checkout <branch>
git pull --ff-only origin <branch>
```

Using `--ff-only` ensures local branches haven't diverged from origin. If the
pull fails, **stop** and report the error.

---

## Step 2 — Cascade merge loop

For each consecutive pair `(SOURCE, TARGET)` in `BRANCHES`:

### 2a. Merge

```bash
git checkout <TARGET>
git merge <SOURCE>
```

Three outcomes are possible:

- **Already up-to-date:** print "✓ `<TARGET>` already up-to-date with `<SOURCE>`"
and skip to the next pair.
- **Clean merge (no conflicts):** git creates the merge commit automatically.
Proceed directly to step 2c.
- **Conflicts:** proceed to step 2b.

### 2b. Resolve conflicts (only when git reports conflicts)

List conflicts:

```bash
git diff --name-only --diff-filter=U
```

Read each conflicted file, resolve it, then `git add` it. When all are resolved:

```bash
git commit --no-edit
```

#### Conflict resolution rules

| File pattern | Strategy |
|---|---|
| `CHANGELOG*.md` | Keep entries from both sides; newer branch entries on top |
| Version constants, `composer.json` branch aliases | Keep the TARGET branch value |
| `composer.json` dependency versions | Keep the TARGET branch value (newer branch may require higher versions) |
| Code files | Merge logically based on context; when unsure, ask the user |

After resolving, show `git diff HEAD~1` (first parent of the merge commit, i.e.
the previous TARGET state) and wait for the user to confirm the resolution looks
correct before proceeding.

### 2c. Run tests

Run the test suite to verify the merge didn't break anything:

```bash
composer install
vendor/bin/phpunit
```

If the project uses `castor`, prefer:

```bash
composer install
castor phpunit
```

If tests fail, first check whether the failure is pre-existing: run the same
test on the TARGET branch before the merge. Only fix failures introduced by the
merge:
1. Analyze and fix the code.
2. Commit the fix with a descriptive message.
3. Re-run failing tests until green.

Report any pre-existing failures to the user without attempting to fix them.

### 2d. Ask for confirmation before pushing

Show:

```
Merge: <SOURCE> → <TARGET>
Tests: all passing

Commits since origin/<TARGET>:
git log --oneline origin/<TARGET>..<TARGET>

Ready to push? (yes / no)
```

**Wait for confirmation.** The user may make changes themselves before confirming.

### 2e. Push and continue

```bash
git push origin <TARGET>
```

If the push fails, **stop** and report the error.

Print "✓ `<SOURCE>` → `<TARGET>` done." and continue to the next pair.

---

## Final summary

```
All merges complete:
3.1.x → 3.2.x ✓
3.2.x → 3.3.x ✓
3.3.x → 4.0.x ✓
```

---

## Gotchas

- `CHANGELOG.md` conflicts are the most common; entries must be kept from both
sides, never dropped.
- A merge can introduce test failures even without conflicts, because behavior
from the older branch may be incompatible with newer code. Always run tests.
- When merging across major versions (e.g. 3.x → 4.x), pay extra attention to
breaking changes, removed deprecations, and updated PHP version requirements.

## Error handling

- **Never** force-push or rewrite history.
- **Never** use `--no-verify` on commits.
- **Never** auto-recover from a failed `git push` or `git pull`. Stop and hand
control back to the user.
60 changes: 48 additions & 12 deletions .ci-tools/phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -282,12 +282,6 @@ parameters:
count: 3
path: ../src/OtherObject/DoublePrecisionFloatObject.php

-
rawMessage: 'Parameter #2 $data of class CBOR\OtherObject\DoublePrecisionFloatObject constructor expects string|null, string|false given.'
identifier: argument.type
count: 1
path: ../src/OtherObject/DoublePrecisionFloatObject.php

-
rawMessage: Class "CBOR\OtherObject\FalseObject" is not allowed to extend "CBOR\OtherObject".
identifier: ergebnis.noExtends
Expand All @@ -312,6 +306,24 @@ parameters:
count: 1
path: ../src/OtherObject/GenericObject.php

-
rawMessage: Binary operation "&" between mixed and 8388607 results in an error.
identifier: binaryOp.invalid
count: 1
path: ../src/OtherObject/HalfPrecisionFloatObject.php

-
rawMessage: Binary operation ">>" between mixed and 23 results in an error.
identifier: binaryOp.invalid
count: 1
path: ../src/OtherObject/HalfPrecisionFloatObject.php

-
rawMessage: Cannot access offset 1 on array|false.
identifier: offsetAccess.nonOffsetAccessible
count: 2
path: ../src/OtherObject/HalfPrecisionFloatObject.php

-
rawMessage: Class "CBOR\OtherObject\HalfPrecisionFloatObject" is not allowed to extend "CBOR\OtherObject".
identifier: ergebnis.noExtends
Expand Down Expand Up @@ -414,12 +426,6 @@ parameters:
count: 3
path: ../src/OtherObject/SinglePrecisionFloatObject.php

-
rawMessage: 'Parameter #2 $data of class CBOR\OtherObject\SinglePrecisionFloatObject constructor expects string|null, string|false given.'
identifier: argument.type
count: 1
path: ../src/OtherObject/SinglePrecisionFloatObject.php

-
rawMessage: Class "CBOR\OtherObject\TrueObject" is not allowed to extend "CBOR\OtherObject".
identifier: ergebnis.noExtends
Expand Down Expand Up @@ -564,6 +570,24 @@ parameters:
count: 1
path: ../src/Tag/Base64UrlTag.php

-
rawMessage: Binary operation "&" between mixed and 4503599627370495 results in an error.
identifier: binaryOp.invalid
count: 1
path: ../src/Tag/BigFloatTag.php

-
rawMessage: Binary operation ">>" between mixed and 52 results in an error.
identifier: binaryOp.invalid
count: 1
path: ../src/Tag/BigFloatTag.php

-
rawMessage: Cannot access offset 1 on array|false.
identifier: offsetAccess.nonOffsetAccessible
count: 2
path: ../src/Tag/BigFloatTag.php

-
rawMessage: Class "CBOR\Tag\BigFloatTag" is not allowed to extend "CBOR\Tag".
identifier: ergebnis.noExtends
Expand Down Expand Up @@ -708,6 +732,18 @@ parameters:
count: 1
path: ../src/Tag/NegativeBigIntegerTag.php

-
rawMessage: Class "CBOR\Tag\SelfDescribeCBORTag" is not allowed to extend "CBOR\Tag".
identifier: ergebnis.noExtends
count: 1
path: ../src/Tag/SelfDescribeCBORTag.php

-
rawMessage: 'Method CBOR\Tag\SelfDescribeCBORTag::createFromLoadedData() has parameter $data with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
count: 1
path: ../src/Tag/SelfDescribeCBORTag.php

-
rawMessage: 'Method CBOR\Tag\TagInterface::createFromLoadedData() has parameter $data with a nullable type declaration.'
identifier: ergebnis.noParameterWithNullableTypeDeclaration
Expand Down
4 changes: 2 additions & 2 deletions .ci-tools/rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
}
$builder->withSets([
SetList::DEAD_CODE,
LevelSetList::UP_TO_PHP_81,
LevelSetList::UP_TO_PHP_80,
DoctrineSetList::DOCTRINE_CODE_QUALITY,
DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
PHPUnitSetList::PHPUNIT_CODE_QUALITY,
PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES,
PHPUnitSetList::PHPUNIT_120,
]);
$builder->withComposerBased(twig: true, doctrine: true, phpunit: true, symfony: true);
$builder->withPhpVersion(PhpVersion::PHP_81);
$builder->withPhpVersion(PhpVersion::PHP_80);
$builder->withPaths(
[
__DIR__ . '/../src',
Expand Down
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
/.ci-tools export-ignore
/.github export-ignore
/bin export-ignore
/doc export-ignore
/tests export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.gitsplit.yml export-ignore
/castor.php export-ignore
/.agents export-ignore
Loading
Loading