Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ac5d03c
chore: move versions in a single place, which is the version catalogue
u-ways-e Nov 3, 2025
1bf962f
refactor: the project version is set either via the environment varia…
u-ways-e Nov 3, 2025
247ece9
feat: add provider extension functions for plugin dependency mapping …
u-ways-e Nov 3, 2025
8e5a582
refactor: move classes to appropriate packages, set plugins to public…
u-ways-e Nov 3, 2025
d8da03b
fix: replace print statement to a logger to enable flexibility of wha…
u-ways-e Nov 3, 2025
4cf78ef
refactor: change RepositoryCredentials class to a data class, see: ht…
u-ways-e Nov 3, 2025
b6b68bf
refactor: rename GitHubCLIProcess to GhCLIProcess for consistency as …
u-ways-e Nov 3, 2025
0959653
fix: suppress unstable API usage warning in GhCliAuthSettingsPlugin
u-ways-e Nov 3, 2025
aad6757
refactor: create a GH auth base for the plugin, extract duplication, …
u-ways-e Nov 4, 2025
d4a4cd3
refactor: rename GhCliProcess to GhCliAuthProcessor for clarity, impr…
u-ways-e Nov 4, 2025
e55eb85
fix: set the GitHub Packages repository name to use the configured or…
u-ways-e Nov 4, 2025
8423c27
fix: change create to register for plugin definitions in build.gradle…
u-ways-e Nov 5, 2025
6a2bd44
fix: get rid of all the project warnings, align kotlin version to emb…
u-ways-e Nov 6, 2025
79a0dda
refactor: enable support for custom GH binary path so users will alwa…
u-ways-e Nov 6, 2025
1c77bc5
feat: add fake GitHub CLI authentication for functional tests to fina…
u-ways-e Nov 6, 2025
992cba0
refactor: implement functional test setup abstract to greatly reduce …
u-ways-e Nov 6, 2025
5266f03
ci: add --info flag to gradlew build command for improved logging dur…
u-ways-e Nov 6, 2025
fe6ddd8
refactor: update token naming convention from 'gh-cli-auth-token' to …
u-ways-e Nov 6, 2025
d175bc7
chore: add '*.salive' to .gitignore to exclude live session files fro…
u-ways-e Nov 6, 2025
8fcf6fe
feat: add support for allowing custom gradle property keys to collect…
u-ways-e Nov 6, 2025
be66c92
cleanup: remove unnecessary settings.gradle.kts in test resources
u-ways-e Nov 6, 2025
788cc1a
docs: update README to enhance structure and clarify plugin usage
u-ways-e Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:

- name: Build
shell: bash
run: ./gradlew build
run: ./gradlew build --info
env:
GH_TOKEN: ${{ secrets.TEST_PAT }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ out/
*.iml
*.ipr
*.iws
*.salive
.project
.settings
.classpath
Expand Down
241 changes: 170 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,115 +1,214 @@
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth.svg?label=gh-cli-auth%20Settings%20Plugin)](https://plugins.gradle.org/plugin/io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth)
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.adelinosousa.gradle.plugins.project.gh-cli-auth.svg?label=gh-cli-auth%20Project%20Plugin)](https://plugins.gradle.org/plugin/io.github.adelinosousa.gradle.plugins.project.gh-cli-auth)

# GitHub CLI Auth Gradle Plugin

Gradle plugin that automatically configures access to GitHub organization maven plugins and packages. Authenticates using credentials from GitHub CLI and removes the need to store personal access tokens (PATs) in your project, environment or gradle configuration.
[![Kotlin](https://img.shields.io/badge/Kotlin-%237F52FF.svg?logo=kotlin&logoColor=white)](#)
[![Continuous Integration](https://github.com/adelinosousa/gh-cli-auth/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/adelinosousa/gh-cli-auth/actions/workflows/pr-checks.yml)
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth.svg?label=Settings%20Plugin)](https://plugins.gradle.org/plugin/io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth)
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/io.github.adelinosousa.gradle.plugins.project.gh-cli-auth.svg?label=Project%20Plugin)](https://plugins.gradle.org/plugin/io.github.adelinosousa.gradle.plugins.project.gh-cli-auth)

1. [Overview](#overview)
2. [Features](#features)
3. [Installation](#installation)
- [A) Settings Plugin (Recommended)](#a-settings-plugin-recommended)
- [B) Project Plugin (Per Project)](#b-project-plugin-per-project)
4. [Usage](#usage)
- [1) Required: Set Your GitHub Organization](#1-required-tell-the-plugin-which-organization-to-use)
- [2) Choose How to Provide Credentials](#2-choose-how-you-want-to-provide-credentials)
5. [Configuration Options](#configuration-options)
- [Token Resolution Order](#token-resolution-order)
- [GitHub CLI Scopes](#github-cli-scopes-cli-fallback)
- [Repository Configuration](#repository-thats-registered)
6. [CI Tips](#ci-tips)
7. [Troubleshooting](#troubleshooting)
8. [Limitations](#limitations)
9. [Contributing](#contributing)
10. [License](#license)

## Overview

**Zero‑boilerplate access to GitHub Packages (Maven) for your organization.**

This plugin family configures the GitHub Packages Maven repository for your org and provides credentials automatically from one of three sources (in order):

1. **Environment variable** (name configurable, default `GITHUB_TOKEN`)
2. **Gradle property** (key configurable, default `gpr.token`)
3. **GitHub CLI**: parses `gh auth status --show-token` (requires `read:packages, read:org`)

> [!NOTE]
> This allows you to onboard this plugin to existing production CI/CD pipelines with minimal changes, while also supporting local development via the GitHub CLI.

It works as a **settings** plugin (centralized repository management for the whole build) and/or a **project** plugin (per‑project repository + a `ghCliAuth` extension to read the token).

## Features

- Registers your authenticated GitHub Packages Maven repository for your organization automatically.
- Complete backwards compatibility with existing environment-based and Gradle property-based token provisioning.
- Ensures common “trusted” repos are present at settings level (added *only if missing*) such as Maven Central and Gradle Plugin Portal.
- Most importantly, No need to rely on hardcoded tokens local configs anymore, just use the GitHub CLI for local dev!

## Prerequisites
## Installation

You need to have [GitHub CLI](https://cli.github.com/) installed on your system and be logged in to your GitHub account:
You can use **either** plugin—or **both** together.

```bash
gh auth login --scopes "read:packages,read:org"
> [!TIP]
> **Recommendation:** In multi‑module builds (or when using `RepositoriesMode.FAIL_ON_PROJECT_REPOS`), prefer the **settings** plugin to centralize repository configuration. The **project** plugin declares repositories at project level and may conflict with `FAIL_ON_PROJECT_REPOS`.

### A) Settings plugin (recommended)

**Kotlin DSL – `settings.gradle.kts`**

```kotlin
plugins {
id("io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth") version "2.0.0"
}
```

**Groovy DSL – `settings.gradle`**

```groovy
plugins {
id 'io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth' version '2.0.0'
}
```

If you're already logged in but don't have the required scopes, you can refresh your authentication using:
With the settings plugin applied, your build will have:

- **GitHub Packages** repo for your org in both `pluginManagement` and `dependencyResolutionManagement`.
- **Default** repos added if missing: Gradle Plugin Portal, Google, Maven Central.
- A shared token available at `gradle.extra["gh.cli.auth.token"]`.

### B) Project plugin (per project)

```bash
gh auth refresh --scopes "read:packages,read:org"
**Kotlin DSL – `build.gradle.kts`**

```kotlin
plugins {
id("io.github.adelinosousa.gradle.plugins.project.gh-cli-auth") version "2.0.0"
}
```

To check your current GitHub CLI authentication status, do:
**Groovy DSL – `build.gradle`**

```bash
gh auth status
```groovy
plugins {
id 'io.github.adelinosousa.gradle.plugins.project.gh-cli-auth' version '2.0.0'
}
```

With the project plugin applied, your project will have:
- **GitHub Packages** repo for your org at `project.repositories`.
- The **`ghCliAuth`** extension exposing the token:
- Kotlin: `val token: String? = extensions.getByName("ghCliAuth") as io.github.adelinosousa.gradle.extensions.GhCliAuthExtension; token.token.get()`
- Groovy: `def token = extensions.getByName("ghCliAuth").token.get()`

## Usage

This plugin is split into two: one for `settings` and the other for `project`. Depending on your solution repository management, you can choose to use either one or both.
### 1) Required: Tell the plugin which **organization** to use

1. Setup for `settings`:
Add this to your **`gradle.properties`** (root of the build):

In your `settings.gradle` file, add the following:
```properties
gh.cli.auth.github.org=<your-organization>
````

```shell
# settings.gradle

# (optional) ensure that the repositories are resolved from settings.gradle
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
}
### 2) Choose how you want to provide credentials

plugins {
id 'io.github.adelinosousa.gradle.plugins.settings.gh-cli-auth' version '1.1.0'
}
```

If you need to consume the token in your own settings plugin, you can access it via gradle extra properties:
You can do nothing (and rely on the GitHub CLI path below), or pick one of these:

```shell
if (settings.gradle.extra.has("gh-cli-auth-token")) {
val ghToken = settings.gradle.extra["gh-cli-auth-token"] as String
}
```
- **Environment variable** (fastest for CI):
- Leave default: export `GITHUB_TOKEN`
- Or choose a name: set `gh.cli.auth.env.name` in `gradle.properties` and export that variable.

2. Setup for `project`:
- **Gradle property** (CLI args or `gradle.properties`):
- Leave default key: `gpr.token`
- Or choose a key: set `gh.cli.auth.property.name` and pass `-P<that-key>=<token>` (or define it in `gradle.properties`).

In your `build.gradle` file, add the following:
- **GitHub CLI** fallback:
- Make sure `gh` is installed and authenticated with the required scopes:

```shell
# build.gradle
```bash
gh auth login --scopes "read:packages,read:org"
# or, if already logged in:
gh auth refresh --scopes "read:packages,read:org"
gh auth status
```

plugins {
id 'io.github.adelinosousa.gradle.plugins.project.gh-cli-auth' version '1.1.0'
}
```
> [!WARNING]
> If both ENV and Gradle property are absent, the plugin automatically falls back to the GitHub CLI route.

This plugin exposes a `ghCliAuth` extension to access the token, if needed:
## Configuration Options

```shell
# build.gradle
| Key / Surface | Where to set/read | Default | Purpose |
|-------------------------------------|-------------------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------|
| `gh.cli.auth.github.org` | `gradle.properties` | **(required)** | GitHub Organization used to build the repo URL and name the repo entry (`https://maven.pkg.github.com/<org>/*`). |
| `gh.cli.auth.env.name` | `gradle.properties` | `GITHUB_TOKEN` | Name of the environment variable the plugin checks **first** for the token. |
| `gh.cli.auth.property.name` | `gradle.properties` | `gpr.token` | Name of the Gradle property the plugin checks **second** for the token (e.g., pass `-Pgpr.token=...` or define in properties). |
| `gradle.extra["gh.cli.auth.token"]` | **read** in `settings.gradle(.kts)` | n/a | Token shared by the **settings** plugin for use by other settings logic/plugins. |
| `ghCliAuth.token` | **read** in `build.gradle(.kts)` | n/a | Token exposed by the **project** plugin’s extension. |
| `-Dgh.cli.binary.path=/path/to/gh` | JVM/system property | auto‑detect | Override the `gh` binary path used by the CLI fallback. Useful for custom installs (e.g., Homebrew prefix, Nix). |

val ghToken = ghCliAuth.token.get()
```
### Token resolution order

### Important Notes
- When using both plugins, ensure that you **only** apply the plugin version to <u>settings</u> plugin block and not to the <u>project</u> plugin block, as it will lead to a conflict.
- You won't be able to obtain GitHub token from the `ghCliAuth` extension if you're setting `RepositoriesMode` as `FAIL_ON_PROJECT_REPOS`, as it is only _currently_ available in the `project` plugin.
- By default, the settings plugin will configure default repositories for plugins and dependencies (google, mavenCentral, gradlePluginPortal). This is to ensure default repositories are always available.
```
ENV (name = gh.cli.auth.env.name, default GITHUB_TOKEN)
└── if unset/empty → GRADLE PROPERTY (key = gh.cli.auth.property.name, default gpr.token)
└── if unset/empty → GitHub CLI: gh auth status --show-token
```

### Configuration
### GitHub CLI scopes (CLI fallback):

Regardless of which one you use, you need to specify your GitHub **organization**, where the plugins or packages are hosted, in the `gradle.properties` file:
Below is the required scopes for the token retrieved via the GitHub CLI:

```properties
# gradle.properties
- `read:packages`
- `read:org`

gh.cli.auth.github.org=<your-organization>
```
If the token lacks these scopes, the plugin will fail with an error message prompting you to refresh your authentication.

You can also specify custom environment variable name for the GitHub CLI authentication token. Defaults `GITHUB_TOKEN`.
### Repository that’s registered:

```properties
# gradle.properties
`https://maven.pkg.github.com/<org>/*` (name = `<org>`), with credentials automatically supplied by the selected token source.

gh.cli.auth.env.name=<environment-variable-name>
```
> [!NOTE]
> Note on username: when the **CLI** path is used, the plugin extracts your GitHub login and uses it as the repository credential username; when **ENV/Gradle property** is used, the username is left empty.

## CI tips

**NOTE**: Environment variable takes precedence over the GitHub CLI token mechanism. GitHub CLI is used as a fallback if the environment variable is not set.
This is by design, to ensure that the plugin remains performant and skips unnecessary checks/steps during CI/CD runs.
- **GitHub Actions**: the default `GITHUB_TOKEN` environment variable is already present → no extra config needed; just set `gh.cli.auth.github.org`.
- **Local development**: Rely on the GitHub CLI route (make sure you’ve logged in with the correct scopes).

## Notes
## Troubleshooting

Currently **not** supported:
- **“Please set `gh.cli.auth.github.org` in gradle.properties.”**
Add `gh.cli.auth.github.org=<your-org>` to `gradle.properties`.

- Dedicated GitHub Enterprise Servers or Hosts
- Profile selection (the plugin uses the default from `gh`)
- Only Maven repositories are supported (no Ivy or other types)
- **“GitHub CLI token is missing required scopes …”**
Run:

```bash
gh auth refresh --scopes "read:packages,read:org"
gh auth status
```

- **Custom `gh` install not found**
Point the plugin at your binary:

```
./gradlew -Dgh.cli.binary.path=/absolute/path/to/gh <task>
```

- **Using `RepositoriesMode.FAIL_ON_PROJECT_REPOS`**
Prefer the **settings** plugin (the project plugin adds repositories at the project level and may conflict with this mode).

## Limitations

- Only **Maven** repositories are configured.
- GitHub **Enterprise**/custom hosts and CLI **profile selection** are not supported; the CLI path expects `github.com` default auth.

## Contributing
Contributions are welcome! Please read the contributing [guidelines](CONTRIBUTING.md).

PRs and issues are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).

## License

This project is licensed under the AGPL-3.0 License - see the [LICENSE](LICENSE) for details.

___
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
org.gradle.configuration-cache=true
gradle.publish.version=1.1.0
gradle.publish.version=2.0.0
8 changes: 6 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.1.20" }
# The kotlin version here is aligned to the Gradle embedded Kotlin version.
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.0.21" }
gradle-plugin-publish = { id = "com.gradle.plugin-publish", version = "1.3.1" }

[libraries]
mockk = { group = "io.mockk", name = "mockk", version = "1.14.5" }
kotest-assertions-core = { module = "io.kotest:kotest-assertions-core", version = "5.9.1" }
kotest-extensions-jvm = { module = "io.kotest:kotest-extensions-jvm", version = "5.9.1" }
mockk = { module = "io.mockk:mockk", version = "1.14.5" }
Loading