Skip to content
Merged
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
146 changes: 146 additions & 0 deletions .claude/skills/jira-conventions/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
name: jira-conventions
description: "RSRMID Jira conventions — the fields every issue needs (Work Category, Business Unit, Team, Components), this repository's `[COMPONENT][BU]: ` title prefix, choosing the parent epic, the Markdown description format, and the worklog rule for Done and Cancelled. Load before creating, editing, or transitioning a Jira issue."
---

<!-- markdownlint-disable -->
<!-- prettier-ignore-start -->

# Atlassian / JIRA

<!--
Everything outside the jira-conventions:repository markers is identical in every
repository and comes from rtldev-middleware-template. The block between them is rendered
from .github/jira-skill.tsv in rtldev-middleware-workspace. Change either there — a weekly
job in the workspace fails on any copy that differs. The prettier-ignore region keeps the
copies byte-identical under every repository's own prettier config.
-->

<!-- jira-conventions:repository:begin -->

## This Repository

- **Title prefix:** `[JAVA-SDK][<BU>]: `
- **Component:** JAVA-SDK (`10228`)

<!-- jira-conventions:repository:end -->

## Project

- **Cloud ID:** `4e50e119-d5ea-4f89-afb1-d4cd47e40177`
- **Site:** centralnic.atlassian.net
- **Jira project key:** RSRMID (3rd-party Software Integrations / Middleware)
- **Issue types:** Task (`10002`), Bug (`10004`), Story (`10001`), Sub-task (`10003`),
Discovery (`11174`), Cybersecurity (`12171`), Epic (`10000`)
- **Transitions** (global, available from any status): To Do (`11`), In Progress (`21`),
In Review (`41`), Q&A (`61`), Ready for Deployment (`51`), Done (`31`), Stand-by (`71`),
Cancelled (`91`)
- **Account IDs** (assignee, mentions): look them up with `lookupJiraAccountId` by name;
never write one into a repository file — most of these repositories are public

## Fields to Set on Every Issue

Work Category and Business Unit are **required** — the create fails without them. Team,
Components and the parent epic are optional to Jira but set on every RSRMID issue.

| Field | ID | Type | Default |
| ------------- | ------------------- | -------------- | -------------------------------------------------------------------------------- |
| Work Category | `customfield_12383` | select | `13286` — Tech Debt |
| Business Unit | `customfield_10027` | multi-checkbox | `10187` — CentralNic Reseller |
| Team | `customfield_10001` | Atlassian team | `3a19b075-e025-44c3-b3e8-af1a958bc36f` — Channel 3rd Party Software Integrations |
| Components | `components` | component list | see [This Repository](#this-repository) |
| Parent | `parent` | epic | see [Parent Epic](#parent-epic) |

Work Category options: `13284` — Strategic, `13285` — Maintain Revenue /BAU, `13286` — Tech Debt,
`13287` — Security. **Default to Tech Debt** unless told otherwise.

Business Unit options in use here (the field offers ~30, most belong to other teams):

| ID | Value | Prefix abbreviation |
| ------- | ------------------- | ------------------- |
| `10187` | CentralNic Reseller | `CNR` |
| `10050` | Internet.bs | `IBS` |
| `10049` | Moniker | `MON` |
| `10054` | IWMN | `IWMN` |

**Default to CentralNic Reseller.**

Team is the Atlassian Team field. The separate `Team/s` checkbox field (`customfield_10050`) is set
**only on a Story**, to `10162` — Channel - 3rd Party Apps: `"customfield_10050": [{ "id": "10162" }]`.
Leave it unset on every other issue type.

Pass the fields in `additional_fields`, e.g. for a Task:

```json
{
"customfield_12383": { "id": "13286" },
"customfield_10027": [{ "id": "10187" }],
"customfield_10001": "3a19b075-e025-44c3-b3e8-af1a958bc36f",
"components": [{ "id": "<component id>" }]
}
```

## Issue Titles

`[<COMPONENT>][<BU>]: <summary>` — e.g. `[WHMCS][CNR]: DNS save in client area wipes NS records`.

The prefix and the component follow from **the repository the fix lands in**, not from where the
problem was found. For a fix in this repository, take both from [This Repository](#this-repository).
For a fix that lands elsewhere, use that repository's — its own copy of this skill names them, and
rtldev-middleware-workspace's copy lists every repository.

**BU** is the abbreviation of the Business Unit field. Several units go in one bracket separated by
`/`: `[WHMCS][IBS/MON]: `.

Older RSRMID titles use a plain `<scope>: ` prefix (`node-sdk: `, `Workspace: `, `CI: `) — don't copy
a title from an old ticket.

## Parent Epic

Every issue gets a parent epic. Epics are per year, so never reuse a key from memory or from an old
ticket — look them up:

```
project = RSRMID AND issuetype = Epic AND statusCategory != Done ORDER BY created DESC
```

Suggest the best match from that list and confirm it before creating the issue. The usual choices:

- `[RSRMID] Tech Debt <year>` — the default for tooling, CI, dependency and maintenance work
- `[RSRMID] Customer Support <year>` — customer escalations
- `[RSRMID] Capitalisable Tasks <year>` — when told the work is capitalisable
- a feature epic, when the work belongs to one

## Description Format

Always pass `contentFormat: "markdown"` explicitly on `createJiraIssue` / `editJiraIssue` — the
tool's default varies — and write the description in **Markdown**, not Jira wiki markup. Jira stores
it as ADF either way; Markdown is the cheaper way to say it. Wiki markup passed under `markdown` is
stored verbatim and renders as literal text.

| Use (Markdown) | Not (wiki markup) |
| ---------------------- | ---------------------- |
| `### Heading` | `h3. Heading` |
| `**bold**`, `_italic_` | `*bold*`, `__italic__` |
| `` `mono` `` | `{{mono}}` |
| triple-backtick fence | `{code}` … `{code}` |
| `- item` | `* item` |

Use real newline characters in the string, never `\n` escape sequences — those pass through as
plain text and have no formatting effect.

Square brackets are Markdown link syntax, so a bare `[WHMCS][CNR]`-style prefix quoted inside a
description gets escaped. Either wrap it in backticks or drop the brackets when referring to another
issue's title.

## Closing an Issue: Done or Cancelled

Neither **Done** nor **Cancelled** holds without a worklog — automation stamps
`missing-time-spent` and reopens the issue. That includes a cancelled issue nobody worked on:
log the time spent finding that out. Sequence: (1) add a worklog, asking for the amount when it
is not obvious; (2) remove the `missing-time-spent` label if present; (3) transition to Done
(`31`) or Cancelled (`91`).

After opening a pull request for an issue, add the PR URL to the issue as a comment.

<!-- prettier-ignore-end -->
103 changes: 103 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Project Instructions

## Project Overview

Java SDK for the CentralNic Reseller (fka RRPProxy) backend API, successor to the deprecated
Hexonet Java SDK, published to Maven Central. Node is present only for the release tooling,
never for product code.

- **Language / runtime:** Java, built with Maven (`maven.compiler.release` 17 in `pom.xml`)
- **Coordinates:** `io.github.centralnicgroup-opensource:java-sdk`, package
`com.centralnicreseller.apiconnector`
- **Default branch:** `master`

## Architecture

- **The code targets the Java 17 API, whatever JDK runs the build.** `pom.xml` sets
`maven.compiler.release=17`, so never use an API added after 17 — the devcontainer runs
JDK 25.
- **Every build plugin is declared inside the `dev` profile only.** CI and the release both
build with `-Pdev`; a plain `mvn` run uses Maven's default plugin versions.
- **`getVersion()` in `APIClient.java` and the `pom.xml` version are written by the
release** — do not edit them by hand.
- **`target/apidocs` and `target/site` are committed release output** (un-ignored in
`.gitignore`, listed as release assets) — regenerate, never hand-edit.

## Coding Standards

- **Style:** Checkstyle Sun conventions via super-linter (`VALIDATE_JAVA`), config
`.github/linters/sun_checks.xml`.
- CI lints only changed files under `src/main/**/*.java` — test code and untouched files are
not checked, so do not read a clean run as a clean codebase.

## Testing

- **Framework:** JUnit 4 (`junit:junit` 4.13.2), tests in
`src/test/java/com/centralnicreseller/apiconnector/*Test.java`.
- **No real API calls in unit tests.** `APIClientTest` serves canned `[RESPONSE]` bodies
from a local `com.sun.net.httpserver.HttpServer` on `127.0.0.1` (`TestServer`) and points
the client at it with `setURL(...)`.
- `src/test/java/com/centralnicreseller/apiconnector/App.java` is the demo, not a test — it
calls the live OT&E API with `CNR_TEST_USER` / `CNR_TEST_PASSWORD`.

### Running tests

```sh
mvn -B clean site package -Pdev # what the shared java-sdk-test.yml runs
pnpm run test-demo # demo App against OT&E — needs credentials
```

## Build, CI & Policies

- **CI** delegates to
[rtldev-middleware-shareable-workflows](https://github.com/centralnicgroup-opensource/rtldev-middleware-shareable-workflows)
(`java-sdk-test.yml` on pull requests, `java-sdk-release.yml` on push to `master`). Do not
reimplement them in this repository's workflow stubs.
- **CI JDK matrix** comes from the `RTLDEV_MW_CI_JAVA_MATRIX` organisation variable, not from
this repository.
- **Releases:** semantic-release (`.releaserc.json`) deploys to Maven Central through
`maven-settings.xml` with `-Pdev`, writes the changelog to `HISTORY.md` and commits it back
to `master`.
- **Lockfiles:** `pnpm-lock.yaml` is committed deliberately; `package-lock.json` is
git-ignored — pnpm only.
- **Supply chain:** `minimumReleaseAge: 1440` in `pnpm-workspace.yaml` is enforced
workspace-wide — wait out a red build rather than lowering it.
- **Devcontainer:** the frame is in `.devcontainer/`; the shared behaviour comes from the
`devbase` devcontainer Feature (`devbase:2`), JDK 25 and Maven from the `java` Feature.
Never fork devbase's scripts here.
- **Runtime version policy:** Java target from `maven.compiler.release` in `pom.xml`; Node
`engines` and `devEngines.packageManager` (pnpm `^11.0.0`) in `package.json` cover the
release tooling.

## Git Conventions

- **Commit messages:** Conventional Commits with **mandatory scope** —
`<type>(<scope>): <summary>`. Never append a `Co-Authored-By:` trailer.
- **Commit type selection:** `fix`/`feat` are reserved for source changes — they trigger a
release. Everything else uses a non-releasing type: `ci` (workflows, devcontainer),
`build` (build tooling), `chore`, `docs`, `test`, `refactor`.
- **Breaking changes:** add `BREAKING CHANGE: <summary>` to the commit body after a blank
line, and document the consumer upgrade path in the same change.
- **Branch creation:** `git checkout master && git pull --ff-only` before `git checkout -b`
— never branch from a stale local default branch or another feature branch.
- **Branch naming:** prefix with the Jira issue ID — `RSRMID-1234-short-description`.
- **Pull requests:** include the Jira issue link in the description; after opening, add the
PR URL as a comment on the Jira issue.
- **Merging:** rebase-merge (`gh pr merge --rebase`). Squash merges are disabled at the
repository level.

## Atlassian / JIRA

Work is tracked in **Jira Cloud**, project `RSRMID` — not GitHub Issues. Load the
`jira-conventions` skill before creating, editing or transitioning an issue: it carries the
required fields, this repository's title prefix and component, and the worklog rule for Done and Cancelled.

## Do NOT

- Add dependencies without explicit request
- Add `Co-Authored-By:` trailers to commit messages
- Fork the `devbase` devcontainer Feature's scripts into this repository
- Hand-edit `HISTORY.md`, the `getVersion()` string, the `pom.xml` version, `target/apidocs`
or `target/site` — the release owns them
- Commit `.env` or display its contents — it is git-ignored for local environment variables
such as credentials
Loading