home / skills / anton-abyzov / specweave / jira-resource-validator

jira-resource-validator skill

/plugins/specweave-jira/skills/jira-resource-validator

This skill validates Jira projects and boards, auto-creates missing resources, and updates .env to ensure seamless Jira integration.

This is most likely a fork of the sw-jira-resource-validator skill from openclaw
npx playbooks add skill anton-abyzov/specweave --skill jira-resource-validator

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
14.7 KB
---
name: jira-resource-validator
description: Validates JIRA projects and boards exist, auto-creates missing resources. Use when setting up JIRA integration, validating .env configuration, or troubleshooting missing projects/boards. Supports per-project board configuration with JIRA_BOARDS_{ProjectKey} pattern.
allowed-tools: Read, Bash, Write, Edit
---

# Jira Resource Validator Skill

**Purpose**: Validate and auto-create Jira projects and boards, ensuring .env configuration is correct.

**Auto-Activation**: Triggers when Jira setup or validation is needed.

## What This Skill Does

This skill ensures your Jira configuration in `.env` is valid and all resources exist. It's **smart enough** to:

1. **Validate Jira projects** - Check if `JIRA_PROJECT` exists
2. **Prompt for action** - Select existing project or create new one
3. **Validate Jira boards** - Check if boards exist (by ID or name)
4. **Create missing boards** - If board names provided, create them automatically
5. **Update .env with IDs** - Replace board names with actual board IDs after creation

## When This Skill Activates

✅ **Automatically activates when**:
- You set up Jira integration for the first time
- You run `/sw-jira:sync` and resources are missing
- Your `.env` has invalid Jira configuration
- You mention "jira setup" or "jira validation"

## Jira Configuration Structure

### Required .env Variables

```bash
JIRA_API_TOKEN=your_token_here
[email protected]
JIRA_DOMAIN=yourcompany.atlassian.net
JIRA_STRATEGY=board-based
JIRA_PROJECT=PROJECTKEY
JIRA_BOARDS=1,2,3  # IDs (if exist) OR names (if creating)
```

### Smart Per-Board Detection (Mixed Mode Support!)

**The system is smart enough to handle ANY combination of IDs and names:**

**All IDs** (validate existing boards):
```bash
JIRA_BOARDS=1,2,3
```
→ Validates boards 1, 2, 3 exist

**All Names** (create new boards):
```bash
JIRA_BOARDS=Frontend,Backend,Mobile
```
→ Creates 3 boards, updates .env with IDs: `JIRA_BOARDS=101,102,103`

**Mixed IDs and Names** (smart handling!):
```bash
JIRA_BOARDS=101,102,QA,Dashboard
```
→ Validates 101, 102 exist
→ Creates "QA" and "Dashboard" boards
→ Updates .env: `JIRA_BOARDS=101,102,103,104` (all IDs!)

**How it works**: Each entry is checked individually:
- Numeric (e.g., "123") → Validate ID exists
- Non-numeric (e.g., "QA") → Create board with that name
- After creation, .env is updated with ALL board IDs

### NEW: Per-Project Configuration (Advanced - Multiple Projects × Boards)

**Multiple JIRA projects with their own boards:**

```bash
# Multiple projects with their own boards
JIRA_STRATEGY=project-per-team
JIRA_PROJECTS=BACKEND,FRONTEND,MOBILE

# Per-project boards (hierarchical naming)
JIRA_BOARDS_BACKEND=123,456         # Sprint + Kanban (IDs)
JIRA_BOARDS_FRONTEND=Sprint,Bug     # Create these boards
JIRA_BOARDS_MOBILE=789,012,345      # iOS + Android + Release (IDs)
```
→ Validates 3 projects exist: BACKEND, FRONTEND, MOBILE
→ Validates/creates boards per project:
  - BACKEND: Validates boards 123, 456 exist
  - FRONTEND: Creates "Sprint" and "Bug" boards, updates .env with IDs
  - MOBILE: Validates boards 789, 012, 345 exist

**Naming Convention**: `{PROVIDER}_{RESOURCE_TYPE}_{PROJECT_KEY}`

**Mixed IDs and Names Per Project**:
```bash
JIRA_BOARDS_BACKEND=123,NewBoard,456
```
→ Validates 123, 456 exist
→ Creates "NewBoard"
→ Updates .env: `JIRA_BOARDS_BACKEND=123,789,456` (all IDs!)

## Validation Flow

### Step 1: Project Validation

**Check if project exists**:
```bash
# API call to Jira
GET /rest/api/3/project/PROJECTKEY
```

**If project exists**:
```
✅ Project "PROJECTKEY" exists
   ID: 10001
   Name: My Project
```

**If project doesn't exist**:
```
⚠️  Project "PROJECTKEY" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [1]:
```

**Option 1: Select Existing**:
```
Available projects:
1. PROJ1 - Project One
2. PROJ2 - Project Two
3. PROJ3 - Project Three

Select a project [1]:

✅ Updated .env: JIRA_PROJECT=PROJ1
```

**Option 2: Create New**:
```
Enter project name: My New Project

📦 Creating Jira project: PROJECTKEY (My New Project)...
✅ Project created: PROJECTKEY (ID: 10005)
```

### Step 2: Board Validation (Per-Board Smart Detection)

**Scenario A: All Board IDs** (all numeric):
```bash
JIRA_BOARDS=1,2,3
```

**Validation**:
```
Checking boards: 1,2,3...
  ✅ Board 1: Frontend Board (exists)
  ✅ Board 2: Backend Board (exists)
  ⚠️  Board 3: Not found

⚠️  Issues found: 1 board(s)
```

**Scenario B: All Board Names** (all non-numeric):
```bash
JIRA_BOARDS=Frontend,Backend,Mobile
```

**Auto-creation**:
```
Checking boards: Frontend,Backend,Mobile...
  📦 Creating board: Frontend...
  ✅ Created: Frontend (ID: 101)
  📦 Creating board: Backend...
  ✅ Created: Backend (ID: 102)
  📦 Creating board: Mobile...
  ✅ Created: Mobile (ID: 103)

📝 Updating .env with board IDs...
✅ Updated JIRA_BOARDS: 101,102,103

✅ All boards validated/created successfully
```

**Scenario C: Mixed IDs and Names** (SMART!):
```bash
JIRA_BOARDS=101,102,QA,Dashboard
```

**Smart handling**:
```
Checking boards: 101,102,QA,Dashboard...
  ✅ Board 101: Frontend Board (exists)
  ✅ Board 102: Backend Board (exists)
  📦 Creating board: QA...
  ✅ Created: QA (ID: 103)
  📦 Creating board: Dashboard...
  ✅ Created: Dashboard (ID: 104)

📝 Updating .env with board IDs...
✅ Updated JIRA_BOARDS: 101,102,103,104

✅ All boards validated/created successfully
```

## Usage Examples

### Example 1: Fresh Jira Setup

**Scenario**: New project, no Jira resources exist yet

**Action**: Run `/sw-jira:sync`

**What Happens**:
```bash
🔍 Validating Jira configuration...

Checking project: MINIDOOM...
⚠️  Project "MINIDOOM" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [2]: 2

Enter project name: Mini DOOM Tournament

📦 Creating Jira project: MINIDOOM (Mini DOOM Tournament)...
✅ Project created: MINIDOOM (ID: 10005)

Checking boards: Frontend,Backend,Mobile...
📦 Creating boards from names...

Creating board: Frontend in project MINIDOOM...
✅ Board created: Frontend (ID: 101)

Creating board: Backend in project MINIDOOM...
✅ Board created: Backend (ID: 102)

Creating board: Mobile in project MINIDOOM...
✅ Board created: Mobile (ID: 103)

✅ Updated .env: JIRA_BOARDS=101,102,103

🎉 Jira configuration complete! All resources ready.
```

**Result**: `.env` now has correct project and board IDs

### Example 2: Select Existing Project

**Scenario**: Project already exists in Jira

**Action**: Run validation

**What Happens**:
```bash
🔍 Validating Jira configuration...

Checking project: PROJ...
⚠️  Project "PROJ" not found

What would you like to do?
1. Select an existing project
2. Create a new project
3. Cancel

Your choice [1]: 1

Available projects:
1. FRONTEND - Frontend Team
2. BACKEND - Backend Team
3. MOBILE - Mobile Team

Select a project [1]: 2

✅ Updated .env: JIRA_PROJECT=BACKEND
✅ Project "BACKEND" exists

Checking boards: 45,46...
✅ All boards exist
```

### Example 3: Mixed Board IDs (Some Exist, Some Don't)

**Scenario**: Some board IDs are invalid

**Action**: Run validation

**What Happens**:
```bash
🔍 Validating Jira configuration...

Checking project: PROJECTKEY...
✅ Project "PROJECTKEY" exists

Checking boards: 1,2,999...

Board 1: ✅ Exists (Frontend Board)
Board 2: ✅ Exists (Backend Board)
Board 999: ❌ Not found

⚠️  Boards not found: 999

Available boards in project PROJECTKEY:
1. Frontend Board (ID: 1)
2. Backend Board (ID: 2)
3. QA Board (ID: 3)
4. DevOps Board (ID: 4)

Would you like to:
1. Remove invalid board (999) from configuration
2. Replace with correct board ID
3. Create new board

Your choice [2]: 2

Enter correct board ID or name: 3

✅ Updated .env: JIRA_BOARDS=1,2,3
```

## CLI Command

**Manual validation**:
```bash
# From TypeScript
npx tsx src/utils/external-resource-validator.ts

# Or via skill activation
"Can you validate my Jira configuration?"
```

**Validation output**:
```typescript
{
  valid: true,
  project: {
    exists: true,
    key: 'PROJECTKEY',
    id: '10001',
    name: 'My Project'
  },
  boards: {
    valid: true,
    existing: [1, 2, 3],
    missing: [],
    created: []
  },
  envUpdated: false
}
```

## Smart Board Creation Logic (Per-Board Detection)

### Detection Algorithm

```typescript
// Parse JIRA_BOARDS from .env
const boardsConfig = "101,102,QA,Dashboard"; // Mixed!
const boardEntries = boardsConfig.split(',').map(b => b.trim());
const finalBoardIds = [];

// Check EACH board individually
for (const entry of boardEntries) {
  const isNumeric = /^\d+$/.test(entry);

  if (isNumeric) {
    // Entry is a board ID - validate it exists
    const boardId = parseInt(entry);
    const board = await checkBoard(boardId);
    if (board) {
      console.log(`✅ Board ${boardId}: ${board.name} (exists)`);
      finalBoardIds.push(boardId);
    } else {
      console.error(`⚠️  Board ${boardId}: Not found`);
    }
  } else {
    // Entry is a board name - create it
    console.log(`📦 Creating board: ${entry}...`);
    const board = await createBoard(entry, projectKey);
    console.log(`✅ Created: ${entry} (ID: ${board.id})`);
    finalBoardIds.push(board.id);
  }
}

// Update .env if any boards were created
if (createdBoardIds.length > 0) {
  updateEnv({ JIRA_BOARDS: finalBoardIds.join(',') });
}
```

**Key improvement**: Per-board detection instead of all-or-nothing!
- `JIRA_BOARDS=1,2,3` → Validates all IDs
- `JIRA_BOARDS=A,B,C` → Creates all boards
- `JIRA_BOARDS=1,2,C` → Validates 1,2, creates C (mixed!)

### Board Creation API

**Jira REST API** (v3):
```bash
POST /rest/api/3/board
Content-Type: application/json

{
  "name": "Frontend Board",
  "type": "scrum",
  "filterId": 10000,  # Filter for project issues
  "location": {
    "type": "project",
    "projectKeyOrId": "PROJECTKEY"  # CRITICAL: Associates board with project
  }
}

Response:
{
  "id": 101,
  "name": "Frontend Board",
  "type": "scrum"
}
```

**IMPORTANT**: The `location` field is **MANDATORY** to associate the board with a project. Without it, Jira creates the board but leaves it detached, requiring manual connection via the UI.

**Filter creation** (required for board):
```bash
POST /rest/api/3/filter
Content-Type: application/json

{
  "name": "PROJECTKEY Issues",
  "jql": "project = PROJECTKEY"
}

Response:
{
  "id": 10000
}
```

## Configuration Examples

### Example 1: All Names (Create Boards)

**Before** (`.env`):
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=Frontend,Backend,QA,DevOps
```

**After validation**:
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103,104
```

**What happened**:
- Detected non-numeric values (names)
- Created 4 boards in Jira
- Updated .env with actual board IDs

### Example 2: All IDs (Validate Existing)

**Before** (`.env`):
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=1,2,3
```

**After validation**:
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=1,2,3
```

**What happened**:
- Detected numeric values (IDs)
- Validated all boards exist
- No changes needed

### Example 3: Mixed IDs and Names (SMART!)

**Before** (`.env`):
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,QA,Dashboard
```

**After validation**:
```bash
JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103,104
```

**What happened**:
- Validated boards 101, 102 exist
- Created "QA" board (got ID 103)
- Created "Dashboard" board (got ID 104)
- Updated .env with ALL board IDs
- **This is the key feature** - you can mix existing IDs with new board names!

### Example 4: Fix Invalid Project

**Before** (`.env`):
```bash
JIRA_PROJECT=NONEXISTENT
JIRA_BOARDS=1,2
```

**After validation** (user selected existing project):
```bash
JIRA_PROJECT=EXISTINGPROJ
JIRA_BOARDS=1,2
```

**What happened**:
- Project NONEXISTENT not found
- User selected EXISTINGPROJ from list
- Updated .env with correct project key

## Error Handling

### Error 1: Invalid Credentials

**Symptom**: API calls fail with 401 Unauthorized

**Solution**:
```
❌ Jira API authentication failed

Please check:
1. JIRA_API_TOKEN is correct
2. JIRA_EMAIL matches your Jira account
3. JIRA_DOMAIN is correct (yourcompany.atlassian.net)

Generate new token at:
https://id.atlassian.com/manage-profile/security/api-tokens
```

### Error 2: Insufficient Permissions

**Symptom**: Cannot create projects/boards (403 Forbidden)

**Solution**:
```
❌ Insufficient permissions to create resources

You need:
- Project Creator permission (for projects)
- Board Creator permission (for boards)

Contact your Jira administrator to request permissions.
```

### Error 3: Project Key Already Taken

**Symptom**: Project creation fails (key exists)

**Solution**:
```
❌ Project key "PROJ" already exists

Options:
1. Use a different project key
2. Select the existing project
3. Cancel

Your choice [2]:
```

### Error 4: Network/API Errors

**Symptom**: API calls timeout or fail

**Solution**:
```
❌ Jira API error: Request timeout

Please check:
1. Internet connection
2. Jira domain is correct
3. Jira is not down (check status.atlassian.com)

Retry? [Y/n]:
```

## Integration with SpecWeave Workflow

### Automatic Validation

When using `/sw-jira:sync`, validation runs automatically:

```bash
/sw-jira:sync 0014

# Internally calls:
1. validateJiraResources()
2. Fix missing project/boards
3. Proceed with sync
```

### Manual Validation

Run validation independently:

```bash
# Via skill
"Validate my Jira configuration"

# Via TypeScript
npx tsx src/utils/external-resource-validator.ts

# Via CLI (future)
specweave validate-jira
```

## Best Practices

✅ **Use board names for initial setup**:
```bash
JIRA_BOARDS=Sprint-1,Sprint-2,Backlog
```
- System creates boards automatically
- Updates .env with IDs
- One-time setup, then use IDs

✅ **Use board IDs after creation**:
```bash
JIRA_BOARDS=101,102,103
```
- Faster validation (no creation needed)
- More reliable (IDs don't change)

✅ **Keep .env in version control** (gitignored tokens):
```bash
# Commit project/board structure
JIRA_PROJECT=PROJ
JIRA_BOARDS=101,102,103

# Don't commit sensitive data
JIRA_API_TOKEN=<redacted>
JIRA_EMAIL=<redacted>
```

✅ **Document board mapping** (in README):
```markdown
## Jira Boards

- Board 101: Frontend Team
- Board 102: Backend Team
- Board 103: QA Team
```

## Summary

This skill ensures your Jira configuration is **always valid** by:

1. ✅ **Validating projects** - Check if project exists, prompt to select or create
2. ✅ **Validating boards** - Check if boards exist (IDs) or create them (names)
3. ✅ **Auto-updating .env** - Replace board names with IDs after creation
4. ✅ **Clear error messages** - Actionable guidance for all failures
5. ✅ **Non-blocking** - Graceful degradation with manual fallback

**Result**: Zero manual Jira setup - system handles everything!

---

**Skill Version**: 1.0.0
**Introduced**: SpecWeave v0.9.5
**Last Updated**: 2025-11-09

Overview

This skill validates that Jira projects and boards referenced in your .env exist and can automatically create any missing resources. It supports mixed configurations of board IDs and names and can update your .env with the created board IDs. Use it to harden Jira integration, fix invalid config, or automate initial project setup.

How this skill works

The validator reads Jira-related environment variables and checks each project and board via the Jira REST API. Numeric board entries are treated as IDs and validated; non-numeric entries are treated as names and are created in the target project. After creating boards, the skill replaces names with their new IDs in .env so future runs use stable identifiers.

When to use it

  • First-time Jira integration or onboarding a new repository
  • After changing JIRA_PROJECT or JIRA_BOARDS in .env
  • When /sw-jira:sync reports missing resources
  • As a troubleshooting step for 401/403 API errors
  • When migrating from board names to stable board IDs

Best practices

  • Prefer board names for initial setup so the skill can create boards automatically
  • Switch to board IDs in .env after creation for faster, deterministic validation
  • Store sensitive tokens out of version control and commit only keys/IDs
  • Use per-project JIRA_BOARDS_{PROJECTKEY} variables for multiple projects
  • Ensure the API account has project and board creation permissions before running

Example use cases

  • Fresh setup: provide JIRA_PROJECT and board names, run validation to create project/boards and update .env with IDs
  • Partial config: mix existing IDs and new names in JIRA_BOARDS and let the skill validate IDs and create missing boards
  • Multi-project: use JIRA_PROJECTS plus JIRA_BOARDS_{PROJECT} entries to validate/create boards per project
  • Recovery: detect an invalid JIRA_PROJECT and interactively select or create the correct project
  • CI pre-sync: run the validator before /sw-jira:sync to guarantee resources exist

FAQ

Will the skill overwrite my .env?

It only updates the specific Jira variables that change (e.g., replacing board names with created IDs). Other entries remain untouched.

What happens if the API credentials are wrong?

Validation will fail with a 401 and the skill will surface instructions to check JIRA_API_TOKEN, JIRA_EMAIL, and JIRA_DOMAIN.