Git credentials and the reading of pull requests split up and tested, gate down to 28 (v1.37.3) #122

Merged
mi merged 2 commits from mihoe/git-gitea-access into main 2026-10-05 18:30:38 +02:00
Owner

Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation.

The Problem

Two methods of the git and Gitea access are above the Kotlin target of 15:

Method Mutation-CRAP Complexity Mutation score
GitService.authenticated 30.12 6 0.13
GiteaClient.GiteaPullRequest.toOpenPullRequest 16.04 16 0.95

authenticated decides which remote git commands get the configured credentials.
No test looked at that decision: the git tests run against local fixture repositories, whose origin is a path, so every fetch ran without credentials and 7 of 8 mutants survived.
toOpenPullRequest maps Gitea's answer and is well tested, but every absent field is a branch of its own.

Non-Goals

  • No change in behaviour.
  • The other groups above 15 follow in their own PRs.

The Scenarios

Feature: remote git commands get credentials only where they can work

Scenario#122.01: only an HTTP(S) origin with account and token fetches through the askpass script

So that the token reaches git exactly where git can use it, and never a prompt blocks a fetch.

  • Given a repository whose top level configures git.account and git.token
  • When its origin is an HTTPS or an HTTP URL
  • Then the fetch runs with GIT_ASKPASS, WERKATOR_GIT_ACCOUNT, WERKATOR_GIT_TOKEN and GIT_TERMINAL_PROMPT=0
    • and the credentials are read from the repository's top level, also when the command runs in a subdirectory
    • and the askpass script exists while the command runs and is gone afterwards
  • When the origin is an SSH URL or there is no origin
  • Then the fetch runs with GIT_TERMINAL_PROMPT=0 alone, and no configuration is read
  • When the account or the token is blank
  • Then the fetch runs with GIT_TERMINAL_PROMPT=0 alone
Verified by

Feature: open pull requests are read whatever Gitea leaves out

Scenario#122.02: a pull request without head or base reads as a fork, and the title prefix is matched in any case

So that a sparse or older answer never marks a foreign branch as the repository's own, nor misses a draft.

  • Given Gitea answers a pull request without head and base, titled [wip] lower case
    • and one whose head has no repo_id
    • and one whose title only mentions WIP: in its middle
  • When the open pull requests are read
  • Then the first is a draft from a fork with empty refs
    • and the second is from a fork, since nothing says its branch is the repository's own
    • and the third is no draft
Verified by
  • GiteaClientIntegrationTest a pull request without head or base reads as a fork, and the title prefix is matched in any case (Scenario#122.02), and the Scenario#117.02 test

The Solution

GitService.credentialsFor answers which credentials a repository's remote commands get, null for none; authenticated runs the command with the askpass script or with NO_PROMPT.
GiteaPullRequest.toOpenPullRequest replaces an absent head or base with an empty branch once, the branch answers its ref and commit itself, and isDraft holds the fallback on the title.

A local PIT run of GitService and GiteaClient afterwards:

Method Mutation-CRAP Complexity Mutation score
GitService.authenticated 2.15 2 0.67
GitService.credentialsFor 9 9 1.00
GiteaClient.GiteaPullRequest.toOpenPullRequest 6 6 1.00
GiteaClient.GiteaPullRequest.isDraft 3.03 3 0.86

The highest score left in both classes is 12 (GitService.originBranchCommitTimes).
The project maximum is now NginxProxyManager.resolveSettings at 27.44, so the gate goes down from 31 to 28.

Additional Changes

  • maxMutationCrap in build.gradle.kts lowered from 31 to 28.
  • Version 1.37.3 with its entry in releases.html.

🤖 Generated with Claude Code

> Historic PR-documentation is not maintained along with new PRs — treat it as a snapshot, not as current documentation. ## The Problem Two methods of the git and Gitea access are above the Kotlin target of 15: | Method | Mutation-CRAP | Complexity | Mutation score | |--------------------------------------------------|---------------|------------|----------------| | `GitService.authenticated` | 30.12 | 6 | 0.13 | | `GiteaClient.GiteaPullRequest.toOpenPullRequest` | 16.04 | 16 | 0.95 | `authenticated` decides which remote git commands get the configured credentials. No test looked at that decision: the git tests run against local fixture repositories, whose origin is a path, so every fetch ran without credentials and 7 of 8 mutants survived. `toOpenPullRequest` maps Gitea's answer and is well tested, but every absent field is a branch of its own. ## Non-Goals - No change in behaviour. - The other groups above 15 follow in their own PRs. ## The Scenarios ### Feature: remote git commands get credentials only where they can work #### Scenario#122.01: only an HTTP(S) origin with account and token fetches through the askpass script So that the token reaches git exactly where git can use it, and never a prompt blocks a fetch. - **Given** a repository whose top level configures `git.account` and `git.token` - **When** its origin is an HTTPS or an HTTP URL - **Then** the fetch runs with `GIT_ASKPASS`, `WERKATOR_GIT_ACCOUNT`, `WERKATOR_GIT_TOKEN` and `GIT_TERMINAL_PROMPT=0` - **and** the credentials are read from the repository's top level, also when the command runs in a subdirectory - **and** the askpass script exists while the command runs and is gone afterwards - **When** the origin is an SSH URL or there is no origin - **Then** the fetch runs with `GIT_TERMINAL_PROMPT=0` alone, and no configuration is read - **When** the account or the token is blank - **Then** the fetch runs with `GIT_TERMINAL_PROMPT=0` alone ##### Verified by - [GitServiceCredentialsUnitTest](../../src/test/kotlin/de/hoennig/werkator/git/GitServiceCredentialsUnitTest.kt) ### Feature: open pull requests are read whatever Gitea leaves out #### Scenario#122.02: a pull request without head or base reads as a fork, and the title prefix is matched in any case So that a sparse or older answer never marks a foreign branch as the repository's own, nor misses a draft. - **Given** Gitea answers a pull request without `head` and `base`, titled `[wip] lower case` - **and** one whose head has no `repo_id` - **and** one whose title only mentions `WIP:` in its middle - **When** the open pull requests are read - **Then** the first is a draft from a fork with empty refs - **and** the second is from a fork, since nothing says its branch is the repository's own - **and** the third is no draft ##### Verified by - [GiteaClientIntegrationTest](../../src/test/kotlin/de/hoennig/werkator/gitea/GiteaClientIntegrationTest.kt) `a pull request without head or base reads as a fork, and the title prefix is matched in any case (Scenario#122.02)`, and the Scenario#117.02 test ## The Solution `GitService.credentialsFor` answers which credentials a repository's remote commands get, null for none; `authenticated` runs the command with the askpass script or with `NO_PROMPT`. `GiteaPullRequest.toOpenPullRequest` replaces an absent head or base with an empty branch once, the branch answers its ref and commit itself, and `isDraft` holds the fallback on the title. A local PIT run of `GitService` and `GiteaClient` afterwards: | Method | Mutation-CRAP | Complexity | Mutation score | |--------------------------------------------------|---------------|------------|----------------| | `GitService.authenticated` | 2.15 | 2 | 0.67 | | `GitService.credentialsFor` | 9 | 9 | 1.00 | | `GiteaClient.GiteaPullRequest.toOpenPullRequest` | 6 | 6 | 1.00 | | `GiteaClient.GiteaPullRequest.isDraft` | 3.03 | 3 | 0.86 | The highest score left in both classes is 12 (`GitService.originBranchCommitTimes`). The project maximum is now `NginxProxyManager.resolveSettings` at 27.44, so the gate goes down from 31 to 28. ## Additional Changes - `maxMutationCrap` in `build.gradle.kts` lowered from 31 to 28. - Version 1.37.3 with its entry in `releases.html`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
mi added 1 commit 2026-10-05 16:55:30 +02:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mi changed title from WIP: Git credentials and the reading of pull requests split up and tested to Git credentials and the reading of pull requests split up and tested, gate down to 28 (v1.37.3) 2026-10-05 17:39:57 +02:00
mi added 1 commit 2026-10-05 17:39:58 +02:00
mi merged commit 31c73d3fb2 into main 2026-10-05 18:30:38 +02:00
mi deleted branch mihoe/git-gitea-access 2026-10-05 18:30:38 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mi/werkator#122