From 8dbf3ee8b59885f4039d487319911d6f49103df3 Mon Sep 17 00:00:00 2001 From: Frederic BIDON Date: Mon, 2 Mar 2026 20:47:52 +0100 Subject: [PATCH] chore: doc, test, lint update * updated docs to meet go-openapi standards * fixed discord link * updated dependencies * upgraded tests to use generic variant Signed-off-by: Frederic BIDON --- .github/CONTRIBUTING.md | 119 +++++++++++++++++++++++++-------------- .github/DCO.md | 2 +- .github/wordlist.txt | 39 +++++++++++++ .gitignore | 2 + .golangci.yml | 1 + CODE_OF_CONDUCT.md | 6 +- CONTRIBUTORS.md | 24 ++++---- README.md | 6 +- SECURITY.md | 28 ++++++++-- docs/MAINTAINERS.md | 121 +++++++++++++++++++++++++--------------- docs/STYLE.md | 48 +++++++++++++--- go.mod | 2 +- go.sum | 4 +- pointer_test.go | 84 ++++++++++++++-------------- 14 files changed, 322 insertions(+), 164 deletions(-) create mode 100644 .github/wordlist.txt diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 85707f7..5359dc6 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,48 +1,57 @@ -## Contribution Guidelines +You'll find here general guidelines to contribute to this project. +They mostly correspond to standard practices for open source repositories. -You'll find below general guidelines, which mostly correspond to standard practices for open sourced repositories. +We have tried to keep things as simple as possible. ->**TL;DR** -> -> If you're already an experienced go developer on github, then you should just feel at home with us +> [!NOTE] +> If you're an experienced go developer on github, then you should just feel at home with us > and you may well skip the rest of this document. > -> You'll essentially find the usual guideline for a go library project on github. +> You'll essentially apply the usual guidelines for a go library project on github. + +These guidelines are common to all libraries published on github by the `go-openapi` organization, +so you'll feel at home with any of our projects. -These guidelines are general to all libraries published on github by the `go-openapi` organization. +You'll find more detailed (or repo-specific) instructions in the [maintainer's docs][maintainers-doc]. -You'll find more detailed (or repo-specific) instructions in the [maintainer's docs](../docs). +[maintainers-doc]: ../docs/MAINTAINERS.md -## How can I contribute? +## How can I contribute -There are many ways in which you can contribute. Here are a few ideas: +There are many ways in which you can contribute, not just code. Here are a few ideas: - * Reporting Issues / Bugs - * Suggesting Improvements - * Code - * bug fixes and new features that are within the main project scope - * improving test coverage - * addressing code quality issues - * Documentation - * Art work that makes the project look great +- Reporting issues or bugs +- Suggesting improvements +- Documentation +- Art work that makes the project look great +- Code + - proposing bug fixes and new features that are within the main project scope + - improving test coverage + - addressing code quality issues ## Questions & issues -### Asking questions +### Asking a question + +You may inquire anything about this library by reporting a "Question" issue on github. -You may inquire about anything about this library by reporting a "Question" issue on github. +You may also join our discord server where you may discuss issues or requests. + +[![Discord Server][discord-badge]][discord-url] + +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/twZ9BwT3 ### Reporting issues Reporting a problem with our libraries _is_ a valuable contribution. - You can do this on the github issues page of this repository. Please be as specific as possible when describing your issue. Whenever relevant, please provide information about your environment (go version, OS). -Adding a code snippet to reproduce the issue is great, and as a big time saver for maintainers. +Adding a code snippet to reproduce the issue is great, and a big time saver for maintainers. ### Triaging issues @@ -62,14 +71,16 @@ process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it. If your pull request is not accepted on the first try, don't be discouraged! -If there's a problem with the implementation, hopefully you received feedback on what to improve. +If there's a problem with the implementation, hopefully you've received feedback on what to improve. If you have a lot of ideas or a lot of issues to solve, try to refrain a bit and post focused pull requests. -Think that they must be reviewed by a maintainer and it is easy to lost track of things on big PRs. +Think that they must be reviewed by a maintainer and it is easy to lose track of things on big PRs. We're trying very hard to keep the go-openapi packages lean and focused. -These packages constitute a toolkit: it won't do everything for everybody out of the box, + +Together, these packages constitute a toolkit for go developers: +it won't do everything for everybody out of the box, but everybody can use it to do just about everything related to OpenAPI. This means that we might decide against incorporating a new feature. @@ -80,9 +91,11 @@ However, there might be a way to implement that feature *on top of* our librarie You just need a `go` compiler to be installed. No special tools are needed to work with our libraries. -The go compiler version required is always the old stable (latest minor go version - 1). +The minimal go compiler version required is always the old stable (latest minor go version - 1). + +Our libraries are designed and tested to work on `Linux`, `MacOS` and `Windows`. -If you're already used to work with `go` you should already have everything in place. +If you're used to work with `go` you should already have everything in place. Although not required, you'll be certainly more productive with a local installation of `golangci-lint`, the meta-linter our CI uses. @@ -104,12 +117,12 @@ github will propose to open a pull request on the original repository. Typically you'd follow some common naming conventions: -- if it's a bugfix branch, name it `fix/XXX-something`where XXX is the number of the +- if it's a bug fixing branch, name it `fix/XXX-something` where XXX is the number of the issue on github - if it's a feature branch, create an enhancement issue to announce your intentions, and name it `feature/XXX-something` where XXX is the number of the issue. -> NOTE: we don't enforce naming conventions on branches: it's your fork after all. +NOTE: we don't enforce naming conventions on branches: it's your fork after all. #### Tests @@ -121,10 +134,10 @@ Take a look at existing tests for inspiration, and run the full test suite on yo before submitting a pull request. Our CI measures test coverage and the test coverage of every patch. + Although not a blocking step - because there are so many special cases - this is an indicator that maintainers consider when approving a PR. - -Please try your best to cover about 80% of your patch. +Please try your best to cover at least 80% of your patch. #### Code style @@ -132,13 +145,13 @@ You may read our stance on code style [there](../docs/STYLE.md). #### Documentation -Don't forget to update the documentation when creating or modifying features. +Don't forget to update the documentation when creating or modifying a feature. Most documentation for this library is directly found in code as comments for godoc. -The documentation for the go-openapi packages is published on the public go docs site: +The documentation for this go-openapi package is published on [the public go docs site][go-doc]. - +--- Check your documentation changes for clarity, concision, and correctness. @@ -150,11 +163,14 @@ go install golang.org/x/pkgsite/cmd/pkgsite@latest ``` Then run on the repository folder: + ```sh pkgsite . ``` -This wil run a godoc server locally where you may see the documentation generated from your local repository. +This will run a godoc server locally where you may see the documentation generated from your local repository. + +[go-doc]: https://pkg.go.dev/github.com/go-openapi/jsonpointer #### Commit messages @@ -164,7 +180,7 @@ reference to all the issues that they address. Pull requests must not contain commits from other users or branches. Commit messages are not required to follow the "conventional commit" rule, but it's certainly a good -thing to follow this guidelinea (e.g. "fix: blah blah", "ci: did this", "feat: did that" ...). +thing to follow that convention (e.g. "fix: fixed panic in XYZ", "ci: did this", "feat: did that" ...). The title in your commit message is used directly to produce our release notes: try to keep them neat. @@ -186,7 +202,7 @@ Be sure to post a comment after pushing. The new commits will show up in the pul request automatically, but the reviewers will not be notified unless you comment. Before the pull request is merged, -**make sure that you squash your commits into logical units of work** +**make sure that you've squashed your commits into logical units of work** using `git rebase -i` and `git push -f`. After every commit the test suite should be passing. @@ -195,6 +211,8 @@ Include documentation changes in the same commit so that a revert would remove a #### Sign your work +Software is developed by real people. + The sign-off is a simple line at the end of your commit message, which certifies that you wrote it or otherwise have the right to pass it on as an open-source patch. @@ -204,11 +222,30 @@ PGP-signed commit are greatly appreciated but not required. The rules are pretty simple: -* read our [DCO](./DCO.md) (from [developercertificate.org](http://developercertificate.org/)) -* if you agree with these terms, then you just add a line to every git commit message +- read our [DCO][dco-doc] (from [developercertificate.org][dco-source]) +- if you agree with these terms, then you just add a line to every git commit message - Signed-off-by: Joe Smith +``` +Signed-off-by: Joe Smith +``` using your real name (sorry, no pseudonyms or anonymous contributions.) -You can add the sign off when creating the git commit via `git commit -s`. +You can add the sign-off when creating the git commit via `git commit -s`. + +[dco-doc]: ./DCO.md +[dco-source]: https://developercertificate.org + +## Code contributions by AI agents + +Our agentic friends are welcome to contribute! + +We only have a few demands to keep-up with human maintainers. + +1. Issues and PRs written or posted by agents should always mention the original (human) poster for reference +2. We don't accept PRs attributed to agents. We don't want commits signed like "author: @claude.code". + Agents or bots may coauthor commits, though. +3. Security vulnerability reports by agents should always be reported privately and mention the original (human) poster + (see also [Security Policy][security-doc]). + +[security-doc]: ../SECURITY.md diff --git a/.github/DCO.md b/.github/DCO.md index e168dc4..78a2d64 100644 --- a/.github/DCO.md +++ b/.github/DCO.md @@ -1,4 +1,4 @@ - # Developer's Certificate of Origin +# Developer's Certificate of Origin ``` Developer Certificate of Origin diff --git a/.github/wordlist.txt b/.github/wordlist.txt new file mode 100644 index 0000000..5a29538 --- /dev/null +++ b/.github/wordlist.txt @@ -0,0 +1,39 @@ +CodeFactor +CodeQL +DCO +GoDoc +JSON +Maintainer's +PR's +PRs +Repo +SPDX +TODOs +Triaging +UI +XYZ +agentic +ci +codebase +codecov +config +dependabot +dev +developercertificate +github +godoc +golang +golangci +jsonpointer +linter's +linters +maintainer's +md +metalinter +monorepo +openapi +prepended +repos +semver +sexualized +vuln diff --git a/.gitignore b/.gitignore index 59cd294..885dc27 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ *.cov .idea .env +.mcp.json +.claude/ diff --git a/.golangci.yml b/.golangci.yml index fdae591..dc7c960 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,6 +12,7 @@ linters: - paralleltest - recvcheck - testpackage + - thelper - tparallel - varnamelen - whitespace diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9322b06..bac878f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or + advances + * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -55,7 +57,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All +reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ae1053e..2ebebed 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,17 +8,17 @@ | Username | All Time Contribution Count | All Commits | | --- | --- | --- | -| @fredbi | 54 | https://github.com/go-openapi/jsonpointer/commits?author=fredbi | -| @casualjim | 33 | https://github.com/go-openapi/jsonpointer/commits?author=casualjim | -| @magodo | 3 | https://github.com/go-openapi/jsonpointer/commits?author=magodo | -| @youyuanwu | 3 | https://github.com/go-openapi/jsonpointer/commits?author=youyuanwu | -| @gaiaz-iusipov | 1 | https://github.com/go-openapi/jsonpointer/commits?author=gaiaz-iusipov | -| @gbjk | 1 | https://github.com/go-openapi/jsonpointer/commits?author=gbjk | -| @gordallott | 1 | https://github.com/go-openapi/jsonpointer/commits?author=gordallott | -| @ianlancetaylor | 1 | https://github.com/go-openapi/jsonpointer/commits?author=ianlancetaylor | -| @mfleader | 1 | https://github.com/go-openapi/jsonpointer/commits?author=mfleader | -| @Neo2308 | 1 | https://github.com/go-openapi/jsonpointer/commits?author=Neo2308 | -| @olivierlemasle | 1 | https://github.com/go-openapi/jsonpointer/commits?author=olivierlemasle | -| @testwill | 1 | https://github.com/go-openapi/jsonpointer/commits?author=testwill | +| @fredbi | 54 | | +| @casualjim | 33 | | +| @magodo | 3 | | +| @youyuanwu | 3 | | +| @gaiaz-iusipov | 1 | | +| @gbjk | 1 | | +| @gordallott | 1 | | +| @ianlancetaylor | 1 | | +| @mfleader | 1 | | +| @Neo2308 | 1 | | +| @olivierlemasle | 1 | | +| @testwill | 1 | | _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ diff --git a/README.md b/README.md index 00bd1ae..c52803e 100644 --- a/README.md +++ b/README.md @@ -134,23 +134,19 @@ Maintainers can cut a new release by either: [release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer.svg [release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer -[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonpointer.svg -[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonpointer [gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonpointer [gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonpointer [codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonpointer [codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonpointer -[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F -[doc-url]: https://goswagger.io/go-openapi [godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer [godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonpointer [slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png [slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM [slack-url]: https://goswagger.slack.com/archives/C04R30YMU [discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue -[discord-url]: https://discord.gg/DrafRmZx +[discord-url]: https://discord.gg/twZ9BwT3 [license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg diff --git a/SECURITY.md b/SECURITY.md index 2a7b6f0..1fea2c5 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,14 +6,32 @@ This policy outlines the commitment and practices of the go-openapi maintainers | Version | Supported | | ------- | ------------------ | -| 0.22.x | :white_check_mark: | +| O.x | :white_check_mark: | + +## Vulnerability checks in place + +This repository uses automated vulnerability scans, at every merged commit and at least once a week. + +We use: + +* [`GitHub CodeQL`][codeql-url] +* [`trivy`][trivy-url] +* [`govulncheck`][govulncheck-url] + +Reports are centralized in github security reports and visible only to the maintainers. ## Reporting a vulnerability If you become aware of a security vulnerability that affects the current repository, -please report it privately to the maintainers. +**please report it privately to the maintainers** +rather than opening a publicly visible GitHub issue. + +Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. -Please follow the instructions provided by github to -[Privately report a security vulnerability](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability). +> [!NOTE] +> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". -TL;DR: on Github, navigate to the project's "Security" tab then click on "Report a vulnerability". +[codeql-url]: https://github.com/github/codeql +[trivy-url]: https://trivy.dev/docs/latest/getting-started +[govulncheck-url]: https://go.dev/blog/govulncheck +[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability diff --git a/docs/MAINTAINERS.md b/docs/MAINTAINERS.md index 0c73976..a7a0b76 100644 --- a/docs/MAINTAINERS.md +++ b/docs/MAINTAINERS.md @@ -1,37 +1,33 @@ -# Maintainer's guide +> [!NOTE] +> Comprehensive guide for maintainers covering repository structure, CI/CD workflows, release procedures, and development practices. +> Essential reading for anyone contributing to or maintaining this project. ## Repo structure -Single go module. - -> **NOTE** -> -> Some `go-openapi` repos are mono-repos with multiple modules, -> with adapted CI workflows. +This project is organized as a repo with a single go module. ## Repo configuration -* default branch: master -* protected branches: master -* branch protection rules: +* Default branch: master +* Protected branches: master +* Branch protection rules: * require pull requests and approval - * required status checks: - - DCO (simple email sign-off) - - Lint - - tests completed -* auto-merge enabled (used for dependabot updates) + * required status checks: + * DCO (simple email sign-off) + * Lint + * All tests completed +* Auto-merge enabled (used for dependabot updates and other auto-merged PR's, e.g. contributors update) ## Continuous Integration ### Code Quality checks -* meta-linter: golangci-lint -* linter config: [`.golangci.yml`](../.golangci.yml) (see our [posture](./STYLE.md) on linters) - -* Code quality assessment: [CodeFactor](https://www.codefactor.io/dashboard) +* meta-linter: [golangci-lint][golangci-url] +* linter config: [`.golangci.yml`][linter-config] (see our [posture][style-doc] on linters) +* Code quality assessment: [CodeFactor][codefactor-url] * Code quality badges - * go report card: - * CodeFactor: + * [go report card][gocard-url] + * [CodeFactor][codefactor-url] > **NOTES** > @@ -58,7 +54,7 @@ Coverage threshold status is informative and not blocking. This is because the thresholds are difficult to tune and codecov oftentimes reports false negatives or may fail to upload coverage. -All tests use our fork of `stretchr/testify`: `github.com/go-openapi/testify`. +All tests across `go-openapi` use our fork of `stretchr/jsonpointer` (this repo): `github.com/go-openapi/jsonpointer`. This allows for minimal test dependencies. > **NOTES** @@ -76,7 +72,7 @@ This allows for minimal test dependencies. ### Automated updates * dependabot - * configuration: [`dependabot.yaml`](../.github/dependabot.yaml) + * configuration: [`dependabot.yaml`][dependabot-config] Principle: @@ -84,7 +80,7 @@ This allows for minimal test dependencies. * all updates from "trusted" dependencies (github actions, golang.org packages, go-openapi packages are auto-merged if they successfully pass CI. -* go version udpates +* go version updates Principle: @@ -92,8 +88,14 @@ This allows for minimal test dependencies. * `go.mod` should be updated (manually) whenever there is a new go minor release (e.g. every 6 months). + > This means that our projects always have a 6 months lag to enforce new features from the go compiler. + > + > However, new features of go may be used with a "go:build" tag: this allows users of the newer + > version to benefit the new feature while users still running with `oldstable` use another version + > that still builds. + * contributors - * a [`CONTRIBUTORS.md`](../CONTRIBUTORS.md) file is updated weekly, with all-time contributors to the repository + * a [`CONTRIBUTORS.md`][contributors-doc] file is updated weekly, with all-time contributors to the repository * the `github-actions[bot]` posts a pull request to do that automatically * at this moment, this pull request is not auto-approved/auto-merged (bot cannot approve its own PRs) @@ -101,7 +103,7 @@ This allows for minimal test dependencies. There are 3 complementary scanners - obviously, there is some overlap, but each has a different focus. -* github `CodeQL` +* GitHub `CodeQL` * `trivy` * `govulnscan` @@ -115,43 +117,70 @@ Reports are centralized in github security reports for code scanning tools. ## Releases +**For single module repos:** + +A bump release workflow can be triggered from the github actions UI to cut a release with a few clicks. + The release process is minimalist: * push a semver tag (i.e v{major}.{minor}.{patch}) to the master branch. * the CI handles this to generate a github release with release notes * release notes generator: git-cliff -* configuration: [`cliff.toml`](../.cliff.toml) +* configuration: the `.cliff.toml` is defined as a share configuration on + remote repo [`ci-workflows/.cliff.toml`][remote-cliff-config] + +Commits from maintainers are preferably PGP-signed. Tags are preferably PGP-signed. +We want our releases to show as "verified" on github. + The tag message introduces the release notes (e.g. a summary of this release). The release notes generator does not assume that commits are necessarily "conventional commits". -## Other files +**For mono-repos with multiple modules:** -Standard documentation: +The release process is slightly different because we need to update cross-module dependencies +before pushing a tag. -* [`CONTRIBUTING.md`](../.github/CONTRIBUTING.md) guidelines -* [`DCO.md`](../.github/DCO.md) terms for first-time contributors to read -* [`CODE_OF_CONDUCT.md`](../CODE_OF_CONDUCT.md) -* [`SECURIY.md`](../SECURITY.md) policy: how to report vulnerabilities privately -* [`LICENSE`](../LICENSE) terms -* [`NOTICE`](../NOTICE) on supplementary license terms (original authors, copied code etc) +A bump release workflow (mono-repo) can be triggered from the github actions UI to cut a release with a few clicks. -Reference documentation (released): +It works with the same input as the one for single module repos, and first creates a PR (auto-merged) +that updates the different go.mod files _before_ pushing the desired git tag. + +Commits and tags pushed by the workflow bot are PGP-signed ("go-openapi[bot]"). -* [godoc](https://pkg.go/dev/go-openapi/jsonpointer) +## Other files + +Standard documentation: -## TODOs & other ideas +* [CONTRIBUTING.md][contributing-doc] guidelines +* [DCO.md][dco-doc] terms for first-time contributors to read +* [CODE_OF_CONDUCT.md][coc-doc] +* [SECURITY.md][security-doc] policy: how to report vulnerabilities privately +* [LICENSE][license-doc] terms +* [NOTICE][notice-doc] on supplementary license terms (original authors, copied code etc) -A few things remain ahead to ease a bit a maintainer's job: +Reference documentation (released): -* reuse CI workflows (e.g. in `github.com/go-openapi/workflows`) -* reusable actions with custom tools pinned (e.g. in `github.com/go-openapi/gh-actions`) -* open-source license checks -* auto-merge for CONTRIBUTORS.md (requires a github app to produce tokens) -* more automated code renovation / relinting work (possibly built with CLAUDE) -* organization-level documentation web site -* ... +* [pkg.go.dev (fka godoc)][godoc-url] + + +[linter-config]: https://github.com/go-openapi/jsonpointer/blob/master/.golangci.yml +[local-cliff-config]: https://github.com/go-openapi/jsonpointer/blob/master/.cliff.toml +[remote-cliff-config]: https://github.com/go-openapi/ci-workflows/blob/master/.cliff.toml +[dependabot-config]: https://github.com/go-openapi/jsonpointer/blob/master/.github/dependabot.yaml +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonpointer +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonpointer +[golangci-url]: https://golangci-lint.run/ +[godoc-url]: https://pkg.go.dev/github.com/go-openapi/jsonpointer +[contributors-doc]: ../CONTRIBUTORS.md +[contributing-doc]: ../.github/CONTRIBUTING.md +[dco-doc]: ../.github/DCO.md +[style-doc]: STYLE.md +[coc-doc]: ../CODE_OF_CONDUCT.md +[security-doc]: ../SECURITY.md +[license-doc]: ../LICENSE +[notice-doc]: ../NOTICE diff --git a/docs/STYLE.md b/docs/STYLE.md index 056fdb5..622078d 100644 --- a/docs/STYLE.md +++ b/docs/STYLE.md @@ -2,14 +2,14 @@ > **TL;DR** > -> Let's be honest: at `go-openapi` and `go-swagger` we've never been super-strict on code style etc. +> Let's be honest: at `go-openapi` and `go-swagger` we've never been super-strict on code style and linting. > > But perhaps now (2025) is the time to adopt a different stance. Even though our repos have been early adopters of `golangci-lint` years ago (we used some other metalinter before), our decade-old codebase is only realigned to new rules from time to time. -Now go-openapi and go-swagger make up a really large codebase, which is taxing to maintain and keep afloat. +Now go-openapi and go-swagger together make up a really large codebase, which is taxing to maintain and keep afloat. Code quality and the harmonization of rules have thus become things that we need now. @@ -21,8 +21,13 @@ You should run `golangci-lint run` before committing your changes. Many editors have plugins that do that automatically. -> We use the `golangci-lint` meta-linter. The configuration lies in [`.golangci.yml`](../.golangci.yml). -> You may read for additional reference. +> We use the `golangci-lint` meta-linter. The configuration lies in +> [`.golangci.yml`][golangci-yml]. +> You may read [the linter's configuration reference][golangci-doc] for additional reference. + +This configuration is essentially the same across all `go-openapi` projects. + +Some projects may require slightly different settings. ## Linting rules posture @@ -30,9 +35,32 @@ Thanks to go's original design, we developers don't have to waste much time argu However, the number of available linters has been growing to the point that we need to pick a choice. +### Our approach: evaluate, don't consume blindly + +As early adopters of `golangci-lint` (and its predecessors), we've watched linting orthodoxy +shift back and forth over the years. Patterns that were idiomatic one year get flagged the next; +rules that seemed reasonable in isolation produce noise at scale. Conversations with maintainers +of other large Go projects confirmed what our own experience taught us: +**the default linter set is a starting point, not a prescription**. + +Our stance is deliberate: + +- **Start from `default: all`**, then consciously disable what doesn't earn its keep. + This forces us to evaluate every linter and articulate why we reject it — the disabled list + is a design rationale, not technical debt. +- **Tune thresholds rather than disable** when a linter's principle is sound but its defaults + are too aggressive for a mature codebase. +- **Require justification for every `//nolint`** directive. Each one must carry an inline comment + explaining why it's there. +- **Prefer disabling a linter over scattering `//nolint`** across the codebase. If a linter + produces systematic false positives on patterns we use intentionally, the linter goes — + not our code. +- **Keep the configuration consistent** across all `go-openapi` repositories. Per-repo + divergence is a maintenance tax we don't want to pay. + We enable all linters published by `golangci-lint` by default, then disable a few ones. -Here are the reasons why they are disabled (update: Nov. 2025, `golangci-lint v2.6.1`): +Here are the reasons why they are disabled (update: Feb. 2026, `golangci-lint v2.8.0`). ```yaml disable: @@ -46,6 +74,7 @@ Here are the reasons why they are disabled (update: Nov. 2025, `golangci-lint v2 - paralleltest # we like parallel tests. We just don't want them to be enforced everywhere - recvcheck # we like the idea of having pointer and non-pointer receivers - testpackage # we like test packages. We just don't want them to be enforced everywhere + - thelper # too many false positives on test case factories returning func(*testing.T). See note below - tparallel # see paralleltest - varnamelen # sometimes, we like short variables. The linter doesn't catch cases when a short name is good - whitespace # no added value @@ -55,9 +84,11 @@ Here are the reasons why they are disabled (update: Nov. 2025, `golangci-lint v2 ``` As you may see, we agree with the objective of most linters, at least the principle they are supposed to enforce. -But all linters do not support fine-grained tuning to tolerate some cases and not some others. +But all linters do not support fine-grained tuning to tolerate some cases and not some others. -When this is possible, we enable linters with relaxed constraints: +**Relaxed linter settings** + +When this is possible, we enable linters with relaxed constraints. ```yaml settings: @@ -81,3 +112,6 @@ When this is possible, we enable linters with relaxed constraints: Final note: since we have switched to a forked version of `stretchr/testify`, we no longer benefit from the great `testifylint` linter for tests. + +[golangci-yml]: https://github.com/go-openapi/jsonpointer/blob/master/.golangci.yml +[golangci-doc]: https://golangci-lint.run/docs/linters/configuration/ diff --git a/go.mod b/go.mod index 06a7e74..20caeef 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/go-openapi/jsonpointer require ( - github.com/go-openapi/swag/jsonname v0.25.4 + github.com/go-openapi/swag/jsonname v0.25.5 github.com/go-openapi/testify/v2 v2.4.0 ) diff --git a/go.sum b/go.sum index 88f2899..0530231 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,4 @@ -github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI= -github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag= +github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo= +github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU= github.com/go-openapi/testify/v2 v2.4.0 h1:8nsPrHVCWkQ4p8h1EsRVymA2XABB4OT40gcvAu+voFM= github.com/go-openapi/testify/v2 v2.4.0/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54= diff --git a/pointer_test.go b/pointer_test.go index 4c68758..f92737e 100644 --- a/pointer_test.go +++ b/pointer_test.go @@ -44,35 +44,35 @@ func TestEscaping(t *testing.T) { t.Run("unescaping an escaped string should yield the original", func(t *testing.T) { esc := Escape(original) - assert.Equal(t, "a~1", esc) + assert.EqualT(t, "a~1", esc) unesc := Unescape(esc) - assert.Equal(t, original, unesc) + assert.EqualT(t, original, unesc) }) }) t.Run("with multiple escapes", func(t *testing.T) { unesc := Unescape("~01") - assert.Equal(t, "~1", unesc) - assert.Equal(t, "~01", Escape(unesc)) + assert.EqualT(t, "~1", unesc) + assert.EqualT(t, "~01", Escape(unesc)) const ( original = "~/" escaped = "~0~1" ) - assert.Equal(t, escaped, Escape(original)) - assert.Equal(t, original, Unescape(escaped)) + assert.EqualT(t, escaped, Escape(original)) + assert.EqualT(t, original, Unescape(escaped)) }) t.Run("with escaped characters in pointer", func(t *testing.T) { t.Run("escaped ~", func(t *testing.T) { s := Escape("m~n") - assert.Equal(t, "m~0n", s) + assert.EqualT(t, "m~0n", s) }) t.Run("escaped /", func(t *testing.T) { s := Escape("m/n") - assert.Equal(t, "m~1n", s) + assert.EqualT(t, "m~1n", s) }) }) }) @@ -92,7 +92,7 @@ func TestFullDocument(t *testing.T) { require.NoErrorf(t, err, "Get(%v) error %v", in, err) asMap, ok := result.(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) require.Lenf(t, asMap, testDocumentNBItems(), "Get(%v) = %v, expect full document", in, result) }) @@ -102,7 +102,7 @@ func TestFullDocument(t *testing.T) { require.NoErrorf(t, err, "Get(%v) error %v", in, err) asMap, ok := result.(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) require.Lenf(t, asMap, testDocumentNBItems(), "Get(%v) = %v, expect full document", in, result) t.Run("should set value in doc, with nil name provider", func(t *testing.T) { @@ -113,17 +113,17 @@ func TestFullDocument(t *testing.T) { require.NoError(t, setter.set(asMap, value, nil)) foos, ok := asMap["foo"] - require.True(t, ok) + require.TrueT(t, ok) asArray, ok := foos.([]any) - require.True(t, ok) + require.TrueT(t, ok) require.Len(t, asArray, 2) foo := asArray[0] bar, ok := foo.(string) - require.True(t, ok) + require.TrueT(t, ok) - require.Equal(t, value, bar) + require.EqualT(t, value, bar) }) }) }) @@ -144,14 +144,14 @@ func TestIsEmpty(t *testing.T) { p, err := New("") require.NoError(t, err) - assert.True(t, p.IsEmpty()) + assert.TrueT(t, p.IsEmpty()) }) t.Run("with non-empty pointer", func(t *testing.T) { p, err := New("/obj") require.NoError(t, err) - assert.False(t, p.IsEmpty()) + assert.FalseT(t, p.IsEmpty()) }) } @@ -287,7 +287,7 @@ func TestGetNode(t *testing.T) { t.Run("with aliased map", func(t *testing.T) { asMap, ok := testDocumentJSON(t).(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) alias := aliasedMap(asMap) result, _, err := p.Get(alias) @@ -380,7 +380,7 @@ func TestStruct(t *testing.T) { value, kind, err := pointerA.Get(s) require.NoError(t, err) - require.Equal(t, reflect.Int, kind) + require.EqualT(t, reflect.Int, kind) require.Equal(t, 1, value) _, err = pointerA.Set(&s, 9) @@ -397,7 +397,7 @@ func TestStruct(t *testing.T) { value, kind, err := pointerD.Get(s) require.NoError(t, err) - require.Equal(t, reflect.Int, kind) + require.EqualT(t, reflect.Int, kind) require.Equal(t, 4, value) _, err = pointerD.Set(&s, 6) @@ -455,7 +455,7 @@ func TestOtherThings(t *testing.T) { t.Run("string representation of a pointer", func(t *testing.T) { p, err := New("/obj/a") require.NoError(t, err) - assert.Equal(t, "/obj/a", p.String()) + assert.EqualT(t, "/obj/a", p.String()) }) t.Run("out of bound array index should error", func(t *testing.T) { @@ -515,14 +515,14 @@ func extractFooKeyIndex(t *testing.T, index int) any { t.Helper() asMap, ok := testDocumentJSON(t).(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) // {"foo": [ ... ] } bbb, ok := asMap["foo"] - require.True(t, ok) + require.TrueT(t, ok) asArray, ok := bbb.([]any) - require.True(t, ok) + require.TrueT(t, ok) return asArray[index] } @@ -709,22 +709,22 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) firstNode, ok := jsonDocument.(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) assert.Len(t, firstNode, 2) sliceNode, ok := firstNode["a"].([]any) - require.True(t, ok) + require.TrueT(t, ok) assert.Len(t, sliceNode, 1) changedNode, ok := sliceNode[0].(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) chNodeVI := changedNode["c"] require.IsType(t, 0, chNodeVI) changedNodeValue, ok := chNodeVI.(int) - require.True(t, ok) + require.TrueT(t, ok) - require.Equal(t, 999, changedNodeValue) + require.EqualT(t, 999, changedNodeValue) assert.Len(t, sliceNode, 1) }) @@ -736,15 +736,15 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) firstNode, ok := jsonDocument.(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) assert.Len(t, firstNode, 2) sliceNode, ok := firstNode["a"].([]any) - require.True(t, ok) + require.TrueT(t, ok) assert.Len(t, sliceNode, 1) changedNode, ok := sliceNode[0].(map[string]any) - require.True(t, ok) + require.TrueT(t, ok) assert.Equal(t, 3, changedNode["b"]) assert.Equal(t, 8, changedNode["c"]) }) @@ -764,8 +764,8 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) assert.Len(t, structDoc.A, 1) changedNode := structDoc.A[0] - assert.Equal(t, 4, changedNode.B) - assert.Equal(t, 7, changedNode.C) + assert.EqualT(t, 4, changedNode.B) + assert.EqualT(t, 7, changedNode.C) }) t.Run("with set node 0 with struct", func(t *testing.T) { @@ -779,8 +779,8 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) assert.Len(t, structDoc.A, 1) changedNode := structDoc.A[0] - assert.Equal(t, 3, changedNode.B) - assert.Equal(t, 8, changedNode.C) + assert.EqualT(t, 3, changedNode.B) + assert.EqualT(t, 8, changedNode.C) }) t.Run("with set node c with struct", func(t *testing.T) { @@ -791,7 +791,7 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) require.Len(t, structDoc.A, 1) - assert.Equal(t, 999, structDoc.A[0].C) + assert.EqualT(t, 999, structDoc.A[0].C) }) }) @@ -807,8 +807,8 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) assert.Len(t, setDoc.Coll.Items, 1) changedNode := setDoc.Coll.Items[0] - assert.Equal(t, 4, changedNode.B) - assert.Equal(t, 7, changedNode.C) + assert.EqualT(t, 4, changedNode.B) + assert.EqualT(t, 7, changedNode.C) }) t.Run("with node 0", func(t *testing.T) { @@ -819,8 +819,8 @@ func TestSetNode(t *testing.T) { require.NoError(t, err) assert.Len(t, setDoc.Coll.Items, 1) changedNode := setDoc.Coll.Items[0] - assert.Equal(t, 3, changedNode.B) - assert.Equal(t, 8, changedNode.C) + assert.EqualT(t, 3, changedNode.B) + assert.EqualT(t, 8, changedNode.C) }) t.Run("with node c", func(t *testing.T) { @@ -829,7 +829,7 @@ func TestSetNode(t *testing.T) { _, err = p.Set(setDoc, 999) require.NoError(t, err) require.Len(t, setDoc.Coll.Items, 1) - assert.Equal(t, 999, setDoc.Coll.Items[0].C) + assert.EqualT(t, 999, setDoc.Coll.Items[0].C) }) }) @@ -983,7 +983,7 @@ func TestOffset(t *testing.T) { t.Log(offset, err) require.NoError(t, err) - assert.Equal(t, tt.offset, offset) + assert.EqualT(t, tt.offset, offset) }) } }