Modernize for 1.0.0 — first release in 11 years#1
Merged
Conversation
After ~11 years on `elixir: "~> 1.1"` and `{:plug, "~> 1.0"}`, bump pins
to current stable (1.14) and clean up the project file:
- Rename `Mixfile` -> `MixProject` (post-1.0 convention)
- `Mix.env ==` and `deps:`/`package:` get their parens (warns on 1.15+)
- Drop `applications: [:logger]` — this lib doesn't log
- Add `:files` whitelist so package contents are explicit
- Add `ex_doc` dev dep and `:docs` config so HexDocs renders
- Pull `@version` and `@source_url` into module attrs for reuse
No behavior change to the plug itself yet; that lands next.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pin transitive dep versions so CI builds are reproducible. Standard practice for Hex libraries since ~2019. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Declare `@behaviour Plug` and drop the default arg from `call/2` so the module formally conforms to the Plug contract. The default `_opts \\ []` papered over a signature mismatch — Plug's `call/2` is required to be arity 2 with no default, and the pipeline always passes `init/1`'s return value. Also: - Move the prose docstring from `@doc` (which was attached to `init/1`) up to `@moduledoc`, where it actually belongs. This is what HexDocs renders on the package landing page. - Fix the example block to be valid Markdown (proper heading + 4-space indent so ExDoc renders it as code). - Update the test to call through `init/1` then `call/2`, matching how Plug invokes the pipeline. This is the breaking change that justifies the 1.0 cut: anyone who was somehow calling `ExClacks.call/1` directly (vanishingly unlikely) gets a clean compile error instead of silent behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Beyond the original "header gets set" smoke test, lock down: - `init/1` is the identity (it's half the public surface) - the plug doesn't clobber other response headers already on the conn - the header is set regardless of HTTP method, not just GET/HEAD Group by function with `describe` blocks so failures point at the relevant callback. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Typos: "explantion" -> "explanation", "Prachett's" -> "Pratchett's"
- `####Example:` -> `## Example` (h4 was wrong level under h1, also
needed a space after the hashes)
- Fenced code blocks throughout instead of mixing fenced + indented
- Drop the `mix new` boilerplate ("If available in Hex...") — the
package has been on Hex for a decade
- Bump install snippet from `~> 0.1.0` to `~> 1.0`
- Add a license section pointing at LICENSE.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The MIT text was already in place, but the copyright line was just "Copyright (c) 2015" with no name. Add the holder and extend the year range to the present. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Eleven years after the last release, ship a proper 1.0: - Add CHANGELOG.md (Keep a Changelog format) covering the upgrade - Bump @Version "0.1.1" -> "1.0.0" - Wire CHANGELOG.md and LICENSE.md into the docs extras and package files list - Gitignore /doc (ex_doc output) so it stops following us around The breaking change justifying the major version bump is `call/2` losing its accidental default arg — see CHANGELOG for migration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`mix docs` (added in the 1.0.0 cut) generates HTML/EPUB output into /doc. Don't let it follow us around in `git status`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
asdf/mise users get a consistent toolchain. Versions match the maintainer's other Elixir project (best_place); python/nodejs lines trimmed since this is an Elixir-only library. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`build_embedded` and `start_permanent` are 2015 mix-new boilerplate. Both are no-ops for a library (they only matter for an actual OTP release), so drop them. Bumping the floor to `~> 1.15` lets us assume modern compiler features in any future work and aligns with what the CI matrix will realistically test. 1.14 is end-of-life as of 2026. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Project-level formatter config so `mix format` works out of the box and contributors don't produce non-conforming diffs. Contents are the standard Elixir library default. CI will enforce via `mix format --check-formatted` once that lands. (Existing source already happened to be conformant — no reformatting needed.) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both callbacks are part of the public surface — HexDocs renders specs inline with the function signature, which is part of how readers learn the API. Use `Plug.opts()` (the canonical type from the Plug behaviour) rather than redefining a local `@type opts`. The plug doesn't read from opts itself, but the contract follows the behaviour. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Two jobs, on every PR and push to main: - `test` matrix runs `mix compile --warnings-as-errors` and `mix test` on the floor (Elixir 1.15 / OTP 26) and the ceiling (1.19 / OTP 28), so the version constraint in mix.exs actually means something. - `quality` runs once on the maintainer's pinned toolchain (from .tool-versions), enforcing `mix format --check-formatted` and a clean `mix docs` build. Caches deps and _build keyed on the resolved Elixir/OTP versions so re-runs don't recompile from scratch. Style follows the maintainer's other Elixir project (best_place). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Standard signal-of-life row at the top of the readme. The CI badge points at the workflow that just landed; the license badge derives its text from the Hex.pm metadata, so as long as `licenses: ["MIT"]` stays in mix.exs they stay in sync. The license link assumes `main` as the default branch — if the rename hasn't happened by publish time, GitHub auto-redirects. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bring
ex_clacksup to current Elixir/Plug/HexDocs conventions after about a decade of dormancy, and cut 1.0.0. The plug itself does the same thing it always did; this is a polish + correctness pass.Headline changes:
elixir: "~> 1.1"→"~> 1.14",{:plug, "~> 1.0"}→{:plug, "~> 1.14"}.ExClacksa real Plug: declare@behaviour Plug, drop the accidental_opts \\ []default fromcall/2. This is the one breaking change — direct callers must update toExClacks.call(conn, ExClacks.init([])). Pipeline users are unaffected.mix.exsmodernization:Mixfile→MixProject, paren fixes, package files whitelist,ex_doc+:docsconfig so the HexDocs landing page renders.init/1identity, method coverage), grouped bydescribe,import Plug.Test(notuse).mix newboilerplate.Test plan
mix deps.getand confirm clean fetchmix test— should report 4 tests, 0 failuresmix docs— should build cleanly with no warningsNot done in this PR (separate decisions)
A follow-up reviewer pass surfaced these as worth considering before tagging — none are blockers, all can land in a follow-up if you want this PR merged first:
.formatter.exs(absent —mix formathas no project config).github/workflows/ci.yml(CI matrix across Elixir/OTP)@specand@typeannotations oninit/1/call/2.tool-versionsfor asdf/mise usersbuild_embedded/start_permanent(legacy 2015 boilerplate, no-op for a library)🤖 Generated with Claude Code