Current section

Files

Jump to
erlang_adk docs RELEASING.md
Raw

docs/RELEASING.md

# Releasing Erlang ADK
This is the maintainer checklist for preparing, approving, tagging, and
publishing a release. The commands below describe actions to take only after
their prerequisites and approvals are satisfied. This document does not claim
that `v0.8.0` has been tagged, pushed, or published.
## 1. Establish the release candidate
- [ ] Work from the intended release branch and record the candidate commit.
- [ ] Confirm the worktree contains only reviewed release changes.
- [ ] Confirm `src/erlang_adk.app.src`, the CLI/doctor output, the README, and
`examples/phoenix_adk_ui/mix.exs` all use the intended version.
- [ ] Confirm `CHANGELOG.md`, the current version contract,
`FEATURE_PARITY.md`, `PROVIDER_PROFILES.md`,
`README_EXAMPLE_COVERAGE.md`, `TESTING.md`, and `UPGRADING.md` agree
with the implementation.
- [ ] Preserve both lock files and the Apache-2.0 license.
- [ ] Validate the release's model `provider_profiles` with
`adk_provider_registry:profiles/0`; review binary aliases, concrete
models, endpoint presets/HTTPS hosts, locked options, and credential
source descriptors. Do not place a literal production credential in
version-controlled configuration.
- [ ] Do not include `_build`, `Mnesia.*`, generated `doc`, crash dumps,
Phoenix `_build`/`deps`, local certificates/keys, provider responses, or
secrets.
Useful read-only checks:
```bash
git status --short
git diff --check
git diff --stat
git ls-files | grep -E '(^|/)(_build|deps|Mnesia\.|doc/|rebar3\.crashdump)'
find . -type f \
! -path './.git/*' \
! -path './test/fixtures/mcp_test_key.pem' \
-exec grep -E -l \
'(BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY|AIza[0-9A-Za-z_-]{20,})' {} +
```
The last two commands should produce no release artifact or credential
matches. The excluded PEM is the documented public localhost MCP test key in
`test/fixtures`; it is not a deployment credential. Review filenames only and
use a dedicated secret scanner if the project's release process provides one.
Test placeholders are allowed; real credentials are not.
## 2. Use the verified toolchains
- Erlang/OTP 27.3.4.14 (minimum production patch and root pin).
- Elixir 1.17 or newer on OTP 27 (verified: 1.19.5).
- Node.js for Phoenix browser tests (verified: 24.3.0).
- The repository's `./rebar3`.
Record exact `erl`, `elixir`, `mix`, and `node` versions with the release
evidence.
## 3. Run the core deterministic and package gates
```bash
./rebar3 do clean, compile, eunit, ct, dialyzer
./scripts/coverage.sh
./rebar3 xref
./rebar3 eunit --module=readme_examples_test
./rebar3 eunit --module=readme_workflow_examples_test
./rebar3 ct --suite test/runtime/invocations/adk_concurrency_stress_SUITE.erl
./rebar3 ct --suite test/integrations/stress/adk_v05_stress_SUITE.erl
./rebar3 escriptize
_build/default/bin/adk doctor
_build/default/bin/adk config validate examples/agent.json
./rebar3 ex_doc
./rebar3 hex build
./scripts/verify_hex_package.sh
```
The 1,176 EUnit, six deterministic Common Test, 73.88% coverage, 210-file
Dialyzer, 29 README, four workflow, and 193 focused totals in
[`TESTING.md`](TESTING.md) are historical v0.7 evidence. The recorded
2026-07-17 v0.8 gate passed 1,414 EUnit tests, six deterministic Common Test
cases, Dialyzer over 235 source modules with no warnings, 74.17% line coverage, 244/244
focused provider/profile/Realtime tests, 30 README plus four workflow tests,
and warning-as-error compilation of all three example modules. Common Test
intentionally skipped 22 paid cases in the deterministic command. Do not
approve a later candidate by copying either release's numbers or by running
only the focused modules.
The seven-module post-audit repair regression set passed 67/67, covering
contiguous in-flight multi-frame priority ordering, Anthropic's minimum
`max_tokens` value of one, and the 64 KiB synchronous/streaming Gun
header/trailer cap.
The same v0.8 record includes passing xref, escript, doctor 0.8.0, checked
configuration validation, ExDoc, Hex 0.8.0 build, and extracted-package
compilation verification.
Inspect generated documentation and the Hex tarball/file list. Confirm the
package contains core source, public headers, license, README, changelog,
the provider-profile/version guides, root examples, and the intentionally
packaged Phoenix companion source;
it must exclude the test source tree, build/dependency caches, local data,
generated Phoenix output, credentials, and crash dumps. The verifier enforces
that boundary and also compiles from a clean extracted archive; inspect the
generated docs landing page separately.
The root Rebar3 project currently has no `rebar3 hex audit` gate. Review
`rebar.lock` and upstream security advisories independently; do not claim that
the Phoenix Mix audit covers it.
## 4. Run the Phoenix release gate
```bash
cd examples/phoenix_adk_ui
mix deps.get
mix assets.setup
mix precommit
MIX_ENV=prod mix assets.deploy
MIX_ENV=prod mix release
mix hex.audit
elixir ../../scripts/verify_phoenix_hex_audit.exs
../../scripts/smoke_phoenix_release.sh proxy 4101
../../scripts/smoke_phoenix_release.sh tls 4443
```
The 101 ExUnit and 31 browser/audio test totals are historical v0.7 evidence.
The recorded 2026-07-17 v0.8 `mix precommit` gate passed 103 ExUnit and 40 Node
tests, including negotiated 16/24 kHz voice assertions. Production assets and
release assembly passed, and the assembled release passed both the test-only
trusted-proxy and verified direct-TLS loopback smokes. Each smoke required HTTP
200 from `/health` and clean shutdown. Follow the exact deployment setup in
the companion README.
`mix hex.audit` currently returns non-zero for EEF-CVE-2026-43969 and
EEF-CVE-2026-43966 in Cowlib 2.18.0. This is a known release exception, not a
pass. The wrapper must return zero only after matching that exact known set;
any new or missing finding fails so the exception and documentation are
reviewed. Before approval, the release owner must either:
- use an official dependency release that fixes both advisories and rerun the
complete gate; or
- explicitly accept the documented temporary exception and its reachability
controls in [`SECURITY.md`](../SECURITY.md).
Do not use the partial fork patch, remove the audit, or weaken TLS/header
validation merely to obtain a zero exit status.
## 5. Run opt-in provider gates
Use a release-owned test project and export the key in the same shell. These
commands use network access, quota, and billable API calls.
```bash
export GEMINI_API_KEY="your_api_key_here"
ERLANG_ADK_GEMINI_REST=1 ./rebar3 ct \
--suite test/readme/readme_live_gemini_SUITE.erl
ERLANG_ADK_GEMINI_LIVE=1 ./rebar3 ct \
--suite test/models/gemini/gemini_live_SUITE.erl
```
The REST suite must use `gemini-3.1-flash-lite`; the Live suite must use
`gemini-3.1-flash-live-preview`. Record pass/fail/skip counts and structural
provider reasons without model content or secrets.
The final recorded 0.7 evidence is REST 15/17 with Search and context cache
failing on bounded HTTP 429 retries, and Live 5/5. That evidence is historical
and does not replace a fresh provider run for a later candidate. A release
owner may explicitly accept a provider/quota result, but a skipped or rejected
case must never be reported as passing implementation evidence.
The 2026-07-17 v0.8 REST attempt reached Google, but HTTP 401
`UNAUTHENTICATED` / `ACCESS_TOKEN_TYPE_UNSUPPORTED` rejected the configured
credential shape. This is external credential evidence, not a pass, skip, or
product regression. No v0.8 paid Gemini Live pass is recorded; deterministic
Live broker/transport coverage must not be described as remote-provider
success.
There is currently no first-party paid Common Test suite for OpenAI Responses,
OpenAI Realtime, Anthropic Messages, or an arbitrary compatible endpoint. The
release record must describe their deterministic injected-transport/codec
evidence accurately and must not infer paid-provider success from configured
environment variables. If the release owner runs a manual smoke, record it as
separate provider evidence without prompts, outputs, or credentials. Each
compatible endpoint is a distinct target, not a blanket certification.
## 6. Approve the release record
Before creating a tag, record:
- candidate commit and toolchain versions;
- deterministic core, focused, stress, CLI, docs, and package results;
- Phoenix format/compile/test/browser/assets/release/runtime results;
- paid REST and Live model, date, counts, and non-secret failure reasons;
- root dependency review and the exact `mix hex.audit` output/status;
- accepted known limitations, including node locality and partial adapters;
- secret-scan/package-content review; and
- the person or process accepting each security/provider exception.
Do not mark the release approved while version metadata or documentation is
stale, a deterministic gate fails, an unexplained test skips, or an advisory
has been hidden.
## 7. Commit, tag, and publish only after approval
Review and commit the release candidate using the repository's normal review
process. Verify the commit before tagging:
```bash
git status --short
git show --stat --oneline HEAD
```
Create the immutable tag only when the candidate commit is approved. Prefer a
signed tag where maintainer signing is configured; otherwise use an annotated
tag and preserve the external approval record:
```bash
git tag -s v0.8.0 -m "Erlang ADK 0.8.0"
# or, when signing is unavailable:
git tag -a v0.8.0 -m "Erlang ADK 0.8.0"
```
Verify the tag points to the approved commit, then push the branch/tag through
the repository's protected release process. Publication is a separate
credentialed action:
```bash
git show --no-patch --decorate v0.8.0
git push origin version_0.8.0
git push origin v0.8.0
./rebar3 hex publish
```
Do not run these commands from an unreviewed or dirty worktree. Never place a
Hex API key, Gemini key, OAuth secret, signing key, or package credential in a
command that will be logged.
## 8. Post-publication verification
- [ ] Verify the Git tag and release notes resolve to the approved commit.
- [ ] Download the published package in a clean environment and compile it on
OTP 27.
- [ ] Verify generated API documentation and README/changelog links.
- [ ] Run a minimal deterministic agent/config smoke test from the package.
- [ ] Confirm advisories and accepted limitations are visible in the release
notes.
- [ ] Retain the complete release evidence without credentials or model/user
content.
If a package or tag is wrong, do not move an existing public tag or silently
replace an immutable package. Publish a corrective version and document the
superseded artifact. If credentials or sensitive data escaped, rotate/revoke
them immediately and follow the private security process.