# RPM -- Gradle Task Runner

Getting started with RPM using Gradle as your task runner. The generated `build.gradle` and `rpm-bootstrap.gradle` wrap the RPM CLI and auto-apply Gradle scripts from synced packages.

---

## Prerequisites

- Java 17+ (`java --version`)
- Gradle (`gradle --version`) -- needed once to generate the Gradle wrapper
- Git

The RPM CLI is already installed (it just ran `rpm bootstrap` to create these files).

---

## Setup

### 1. Generate the Gradle Wrapper

The Gradle wrapper (`gradlew`) is not generated by `rpm bootstrap`. Create it once using your locally installed Gradle:

```bash
gradle wrapper
```

This creates `gradlew`, `gradlew.bat`, and `gradle/wrapper/` in the project directory. You only need to run this once per environment.

### 2. Edit `.rpmenv`

Replace all `<PLACEHOLDER>` values with your project's configuration. See the `.rpmenv` Variable Reference section below for details on each variable.

### 3. Customize `build.gradle`

Replace the project-specific section at the bottom of `build.gradle` with your own `group` and `version`. RPM provides plugins via synced packages but does not manage dependency versions -- each project owns its version pins and BOM imports.

### 4. Configure (sync all packages)

```bash
./gradlew rpmConfigure
```

This delegates to `rpm configure .rpmenv`, which syncs all packages to `.packages/` and updates `.gitignore`.

### 5. Verify

```bash
./gradlew tasks
```

After configure, `./gradlew tasks` shows the RPM tasks (`rpmConfigure`, `rpmClean`) plus all tasks contributed by synced build packages.

---

## Usage

**Configure (sync packages):**

```bash
./gradlew rpmConfigure
```

**Clean (full teardown):**

```bash
./gradlew rpmClean
```

**List tasks by group:**

```bash
./gradlew tasks --group rpm
```

**Or use the RPM CLI directly:**

```bash
rpm configure .rpmenv
rpm clean .rpmenv
```

---

## `.rpmenv` Variable Reference

### Core Variables

| Variable | Required | Purpose |
|---|---|---|
| `RPM_CLI_URL` | No | Git URL of the RPM CLI repository. Informational -- records which CLI version the project uses. |
| `RPM_CLI_REV` | No | Git revision (tag or branch) of the RPM CLI. Informational -- records which CLI version the project uses. |
| `REPO_URL` | Yes | Git URL of the [rpm-git-repo](https://github.com/caylent-solutions/rpm-git-repo) tool. Must be `https://github.com/caylent-solutions/rpm-git-repo.git` -- no other repo tool or fork is supported. Used by `rpm configure` to install the repo tool via pipx. |
| `REPO_REV` | Yes | rpm-git-repo version. Currently use `feat/initial-rpm-git-repo` (the only available branch). Once published to PyPI, use a tagged release or PEP 440 specifier (e.g., `~=2.0.0`, `>=2.0.0,<3.0.0`, `*`). |
| `GITBASE` | Yes | Base Git URL for your organization (e.g., `https://github.com/your-org/`). Used by `repo envsubst` to resolve `${GITBASE}` placeholders in manifest XML files. |
| `CLAUDE_MARKETPLACES_DIR` | Conditional | Directory for marketplace plugin symlinks. Required when `RPM_MARKETPLACE_INSTALL=true`. Typically `${HOME}/.claude-marketplaces`. |
| `RPM_MARKETPLACE_INSTALL` | No | Set to `true` to enable the marketplace plugin install/uninstall lifecycle during configure and clean. Default: `false`. When `false`, marketplace-related operations are skipped entirely. |

### Source Variables

Sources are auto-discovered from `RPM_SOURCE_<name>_URL` patterns and processed in alphabetical order by name. Each source requires three variables:

| Variable | Required | Purpose |
|---|---|---|
| `RPM_SOURCE_<name>_URL` | Yes | Git URL of the manifest repository for this source. |
| `RPM_SOURCE_<name>_REVISION` | Yes | Branch, tag, or PEP 440 constraint to track for this source's manifest repository. |
| `RPM_SOURCE_<name>_PATH` | Yes | Path to the entry-point manifest XML file within the manifest repository (e.g., `repo-specs/build/meta.xml`). |

You can define multiple sources. Uncomment the `marketplaces` or `tools` blocks in `.rpmenv` or add your own.

---

## How It Works

`build.gradle` applies `rpm-bootstrap.gradle`, which:

1. Reads `.rpmenv` configuration (with environment variable overrides)
2. Auto-discovers and applies all `*.gradle` scripts from packages in `.packages/`
3. Registers `rpmConfigure` and `rpmClean` tasks that delegate to the RPM CLI

The `buildscript` block in `build.gradle` reads `rpm-manifest.properties` from each synced package to add external plugin JARs (SonarQube, OWASP, Spring Boot) to the build classpath. Core Gradle plugins (`java`, `checkstyle`, `jacoco`) need no entry.

**Committed files:** `.rpmenv`, `build.gradle`, `rpm-bootstrap.gradle`, `rpm-readme.md`

**Ephemeral files (gitignored):** `.packages/`, `.rpm/`, `gradlew`, `gradlew.bat`, `gradle/`

---

## Package Script Access

Gradle package scripts have access to:

- `project.ext.get('_rpmProp')` -- Closure to read `.rpmenv` values (with env var override)
- `project.ext.get('_rpmCurrentPkgDir')` -- Absolute path to the current package directory

Example package script:

```groovy
def rpmProp = project.ext.get('_rpmProp')
def PKG_DIR = project.ext.get('_rpmCurrentPkgDir')
```

---

## Adding Sources

Uncomment or add source blocks in `.rpmenv`:

```properties
RPM_SOURCE_tools_URL=https://github.com/your-org/tools-manifests.git
RPM_SOURCE_tools_REVISION=main
RPM_SOURCE_tools_PATH=repo-specs/tools/meta.xml
```

---

## Marketplace Plugins (Optional)

To enable Claude Code marketplace plugins, set in `.rpmenv`:

```properties
RPM_MARKETPLACE_INSTALL=true
CLAUDE_MARKETPLACES_DIR=${HOME}/.claude-marketplaces
```

Then add a marketplace source and re-run `./gradlew rpmConfigure`. When `RPM_MARKETPLACE_INSTALL` is `false` (the default), the marketplace lifecycle is skipped entirely -- no plugins are installed or uninstalled.

---

## Troubleshooting

- **`./gradlew` not found** -- Run `gradle wrapper` to generate the Gradle wrapper
- **`./gradlew rpmConfigure` fails with "rpm: command not found"** -- Reinstall the RPM CLI: `pipx install rpm-cli`
- **`./gradlew rpmConfigure` fails with ".rpmenv not found"** -- Ensure `.rpmenv` exists in the project root
- **No package tasks after configure** -- Check that packages contain `*.gradle` scripts
- **Plugin dependency errors** -- Ensure packages declare external plugin dependencies in `rpm-manifest.properties`
