Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
63 changes: 63 additions & 0 deletions .claude/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Claude Code Configuration for Seqera Platform CLI

This directory contains Claude Code configuration and skill documentation for contributors working on the Seqera Platform CLI codebase.

## Skills Available

### enrich-cli-help

Workflow documentation for generating structured CLI metadata from the `tower-cli` source tree.

**Use this skill when:**
- Updating the metadata extractor
- Validating metadata output
- Reviewing the release-artifact workflow for CLI docs metadata

**Quick start:**
```bash
./gradlew extractCliMetadata
```

This generates `build/cli-metadata/cli-metadata.json`.

**Documentation:**
- `skills/enrich-cli-help/SKILL.md` - Complete workflow guide
- `skills/enrich-cli-help/README.md` - Quick reference

## Project Context

### Repository Structure
```text
tower-cli/
├── src/main/java/io/seqera/tower/cli/
│ └── utils/metadata/
│ └── CliMetadataExtractor.java
├── docs/
│ └── README.md
├── .claude/
└── build.gradle
```

### Key Files

- `src/main/java/io/seqera/tower/cli/utils/metadata/CliMetadataExtractor.java`
- `build.gradle`
- `docs/README.md`
- `.github/workflows/build.yml`

## Workflow Overview

```text
1. Extract metadata
└─> ./gradlew extractCliMetadata
└─> Outputs build/cli-metadata/cli-metadata.json

2. Verify
└─> Run tests when the extractor changes
└─> Confirm metadata shape stays stable

3. Release
└─> Generate cli-metadata.json in CI
└─> Upload it to GitHub release assets
└─> Dispatch docs automation with the release asset URL
```
36 changes: 36 additions & 0 deletions .claude/skills/enrich-cli-help/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CLI Metadata Generation Skill

This skill documents how to generate and validate structured CLI metadata from the `tower-cli` source tree.

## Quick Start

Run:

```bash
./gradlew extractCliMetadata
```

The output is written to `build/cli-metadata/cli-metadata.json`.

## What This Skill Does

1. Generates CLI metadata from picocli command definitions
2. Verifies the extractor output shape
3. Documents the release-artifact workflow
4. Keeps metadata generation independent from external OpenAPI specs

## Release strategy

- Metadata is generated from source code without modifying it
- Metadata is a build and release artifact, not a tracked repository file
- Downstream docs tooling should consume the release asset

## Files

- `SKILL.md` - Complete skill documentation

## Requirements

- Repository root: `tower-cli`
- Gradle task: `extractCliMetadata`
- Extractor: `src/main/java/io/seqera/tower/cli/utils/metadata/CliMetadataExtractor.java`
73 changes: 73 additions & 0 deletions .claude/skills/enrich-cli-help/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
name: enrich-cli-help
description: Generate structured CLI metadata from tower-cli source code using the built-in Java extractor. Use when validating metadata generation, updating release automation, or checking the downstream artifact consumed by docs tooling.
---

# CLI Metadata Generation for Seqera Platform CLI

This skill is for generating and validating CLI metadata from the `tower-cli` source tree.

## When to Use This Skill

Use this skill when:
- Updating the metadata extractor implementation
- Verifying that the Gradle task still produces valid metadata
- Reviewing release automation for the metadata artifact
- Investigating command coverage in the generated metadata
- Confirming downstream docs consumers can rely on the release artifact

## Scope

The generator is deterministic and works directly from the compiled CLI command tree. It does not edit CLI source code and it does not depend on external OpenAPI specifications.

## Workflow

### Step 1: Generate metadata locally

Run the Gradle task from the repository root:

```bash
./gradlew extractCliMetadata
```

The generated file is written to:

```text
build/cli-metadata/cli-metadata.json
```

### Step 2: Validate the output

Check that the JSON contains the expected top-level keys:

```text
metadata
hierarchy
commands
```

If you are changing the extractor, add or update unit tests under `src/test/`.

### Step 3: Review only the metadata generation path

Focus on:
- `src/main/java/io/seqera/tower/cli/utils/metadata/CliMetadataExtractor.java`
- `build.gradle`
- release automation in `.github/workflows/`
- docs describing metadata generation

Do not mix this workflow with CLI help-text enrichment or external API specs.

### Step 4: Release behavior

At release time the metadata should be:
1. generated from the current `tower-cli` source tree
2. uploaded as a GitHub release artifact
3. passed to downstream docs tooling via the release asset URL

## Notes

- Remove hard-coded local paths from all documentation.
- Keep generated metadata out of Git.
- Prefer battle-tested libraries already on the classpath over hand-written serializers.
- Keep the workflow focused on metadata generation only.
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Comment thread
llewellyn-sl marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,12 @@ jobs:
echo "VERSION=$VERSION"
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT

- name: Generate CLI metadata artifact
run: ./gradlew extractCliMetadata
env:
GITHUB_USERNAME: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Run JReleaser
uses: jreleaser/release-action@v2
env:
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
# Ignore Gradle build output directory
build
**/build-info.properties
docs/cli-metadata.json

# Location for unshared files
.user/
.DS_Store


*.iml

# macOS system files
.DS_Store
**/.DS_Store
13 changes: 13 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ tasks.register('runReflectionConfigGenerator', JavaExec) {
jvmArgs = ["-agentlib:native-image-agent=access-filter-file=conf/access-filter-file.json,config-merge-dir=conf/"]
}

task extractCliMetadata(type: JavaExec) {
group = 'documentation'
description = 'Extract CLI metadata from the source tree using picocli metadata inspection'
classpath = sourceSets.main.runtimeClasspath
mainClass = 'io.seqera.tower.cli.utils.metadata.CliMetadataExtractor'
args = [file('build/cli-metadata/cli-metadata.json').absolutePath]
outputs.file(file('build/cli-metadata/cli-metadata.json'))
dependsOn classes
doFirst {
file('build/cli-metadata').mkdirs()
}
}

Comment thread
JaimeSeqLabs marked this conversation as resolved.
tasks.named('shadowJar') {
archiveBaseName.set('tw')
archiveClassifier.set('')
Expand Down
107 changes: 107 additions & 0 deletions docs/README.md
Comment thread
llewellyn-sl marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# CLI Metadata Generator

This directory documents the CLI metadata generator used by `tower-cli`.

## Overview

The metadata generator inspects the compiled CLI command tree through picocli and emits a structured JSON document for downstream documentation tooling.

The generator:
- lives in the `tower-cli` repository
- is implemented in Java
- runs as the Gradle task `extractCliMetadata`
- does not modify CLI source files
- produces build output that is not tracked in Git

## Manual generation

Generate metadata locally with:

```bash
./gradlew extractCliMetadata
```

The task writes the artifact to:

```text
build/cli-metadata/cli-metadata.json
```

## Output contents

The generated JSON includes:
- top-level extraction metadata
- the full command hierarchy
- a flat command lookup map
- command options, positional parameters, types, arity, and descriptions
- resolved picocli mixins

## Implementation

The extractor is implemented in:

```text
src/main/java/io/seqera/tower/cli/utils/metadata/CliMetadataExtractor.java
```

It builds the `tw` command tree, walks the picocli `CommandSpec` model, filters standard help/version options, and serializes the resulting structure with Jackson.

## Release flow

The metadata file is a release artifact, similar to the CLI binaries.

At release time the build pipeline:
1. runs `./gradlew extractCliMetadata`
2. produces `build/cli-metadata/cli-metadata.json`
3. lets JReleaser publish that file to the GitHub release assets

Downstream consumers should fetch metadata from the release assets rather than from a tracked repository file.

**Documentation:** See `.claude/skills/enrich-cli-help/` for complete workflow guide

## Troubleshooting

### Missing GitHub package credentials

If the build fails with `Username must not be null!`, configure GitHub credentials for the private `tower-java-sdk` dependency:

```bash
# In ~/.gradle/gradle.properties
github.packages.user=your-github-username
github.packages.token=your-github-token
```
Comment thread
llewellyn-sl marked this conversation as resolved.

You can also inline credentials for a one-off run:

```bash
GITHUB_USERNAME=<username> GITHUB_TOKEN=<token> ./gradlew extractCliMetadata
```

or

```bash
GITHUB_USERNAME=<username> GITHUB_TOKEN=$(cat gh_token.txt) ./gradlew extractCliMetadata
```

### Commands missing from output

Check for:
- Proper `@Command` annotation on class
- Parent command has `subcommands = {ChildCmd.class}` reference
- Import statement if subcommand in different package

### Options missing from output

Check for:
- Ensure mixin classes are properly annotated with `@Mixin`
- Verify option annotations: `@Option` or `@CommandLine.Option` (both supported)
- Check that picocli can access the option at runtime

## Related Documentation

- **Java extractor:** `src/main/java/io/seqera/tower/cli/utils/metadata/CliMetadataExtractor.java`
- **Gradle task:** `extractCliMetadata` in `build.gradle`
- **Release workflow:** `.github/workflows/build.yml`
- **JReleaser config:** `jreleaser.yml`
- **Claude Code skill:** `.claude/skills/enrich-cli-help/SKILL.md`
- **CLI documentation:** https://docs.seqera.io/platform/latest/cli/overview
6 changes: 5 additions & 1 deletion jreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ release:
- search: ' \[skip ci\]'
- search: ' \[release\]'

files:
artifacts:
- path: "build/cli-metadata/cli-metadata.json"

distributions:
tw:
type: FLAT_BINARY
Expand Down Expand Up @@ -116,4 +120,4 @@ packagers:
active: RELEASE
tagName: '{{distributionName}}-{{tagName}}'
branch: HEAD
commitMessage: '{{distributionName}} {{tagName}}'
commitMessage: '{{distributionName}} {{tagName}}'
Loading
Loading