# Releasing

Applies to every `t3bootstrap/*` package on git.wappler.systems.

## The two remotes

```
origin / composer  ->  gitea@git.wappler.systems:T3Bootstrap/<repo>.git     development
customers          ->  gitea@git.wappler.systems:T3Bootstrap14/<repo>.git   delivery
```

`.github/workflows/publish-composer-package.yml` triggers on `push: tags` and runs
**in the repository the tag lands in**. Only the `T3Bootstrap14` organisation feeds the
customer Composer registry, so a tag pushed to `origin` alone builds nothing — silently,
with no error anywhere. The tag has to reach `customers` as well.

## Steps

1. Bump `'version'` in `ext_emconf.php`. `composer.json` deliberately carries no `version`
   field — the published version comes from the tag.
2. Commit as `[RELEASE] x.y.z`. Say in the body what changed for consumers, and name any
   dependency constraint that moved with it.
3. Tag **annotated**, with a one-line release note as the message — every existing tag is:
   ```
   git tag -a x.y.z -m "x.y.z

   Short note on what this fixes or adds."
   ```
4. Push both:
   ```
   git push origin release/v14
   git push origin x.y.z
   git push customers x.y.z      # <- this is what builds the package
   ```

`customers` only holds a `main` branch; the code branch is never pushed there. The annotated
tag carries the commit objects it needs along with it, so `git archive` finds the state on
that side.

## Verify

The workflow zips `git archive <tag>` and uploads it to `vars.COMPOSER_UPLOAD_URI`
(`…/api/packages/T3Bootstrap14/composer`) with `?version=<tag>`, authenticating with
`secrets.COMPOSER_UPLOAD_TOKEN`. An existing version of the same number is deleted first, so
re-running a release does not fail with "already exists".

The build takes roughly half a minute. Registry credentials are the customer registry ones —
keep them out of logs and commits.

```
curl -s -u "<user>:<pass>" \
  https://git.wappler.systems/api/packages/T3Bootstrap14/composer/p2/t3bootstrap/<repo>.json
```

Checking that the version number appears is not enough — it only proves *something* was
uploaded. Pull the new version's `dist.url`, unzip it and confirm that `ext_emconf.php` shows
the version you tagged and that the code you released is actually inside. That is what tells
you the tagged state was built, and not a stale one.
