Skip to main content

JPD Field Validation

Overview

The sync tool automatically validates that all required JPD custom fields exist and have the correct types before starting the sync process. This prevents sync failures and provides clear, actionable error messages when fields are missing or misconfigured.

Features

Pre-Sync Validation - Validates fields before any sync operations
Type Checking - Ensures fields have the expected data types
Required vs Optional - Distinguishes between required and optional fields
Helpful Error Reports - Provides clear instructions on how to fix issues
Automatic Detection - Extracts project key from JQL automatically

Configuration

Defining Fields

Add a fields section to your config file:

fields:
# Example: Required numeric field
- id: "customfield_10001"
name: "Impact Score"
type: "number"
required: true
description: "RICE Impact score (0-10)"

# Example: Optional text field
- id: "customfield_10002"
name: "Notes"
type: "text"
required: false
description: "Additional notes"

# Example: Multi-select field
- id: "customfield_10003"
name: "Product Themes"
type: "multiselect"
required: true
description: "Strategic product themes"

Field Properties

PropertyTypeRequiredDescription
idstringJPD custom field ID (e.g., customfield_14377)
namestringHuman-readable field name
typeFieldTypeExpected field type (see below)
requiredbooleanWhether field is required for sync
descriptionstringBrief description (for documentation)
searcherKeystringJira searcher key (for future API creation)

Supported Field Types

TypeDescriptionJPD Examples
stringSingle-line textShort text fields
textMulti-line textLong descriptions
numberNumeric valuesRICE scores, estimates
selectSingle-select dropdownPriority, Status
multiselectMulti-select dropdownThemes, Tags
userUser pickerAssignee, Reporter
dateDate pickerDue date
datetimeDate-time pickerTimestamps
urlURL fieldLinks, references
arrayArray/listGeneric arrays

How It Works

1. Automatic Project Detection

The validator extracts the project key from your JQL:

sync:
jql: "project = YOUR_PROJECT" # Automatically detects "YOUR_PROJECT"

Or from environment variable:

JPD_PROJECT_KEY=YOUR_PROJECT

2. Sample Issue Validation

The validator fetches one issue from the project and checks all configured fields:

  • ✅ Field exists
  • ✅ Field has correct type
  • ✅ Required fields are not null

3. Type Compatibility

The validator understands JPD's field structures:

// Single-select field
{ value: "High Priority" } → type: "select"

// Multi-select field
[{ value: "Theme A" }, { value: "Theme B" }] → type: "multiselect"

// Number field
42 → type: "number"

Validation Results

Success ✅

[INFO] Validating 9 JPD custom fields...
[INFO] ✅ All 8 required fields validated successfully
[WARN] Optional field "Notes" (customfield_14388) is null.
[INFO] Syncing JPD -> GitHub

Failure ❌

╔══════════════════════════════════════════════════════════════╗
║ ║
║ ❌ JPD FIELD VALIDATION FAILED ❌ ║
║ ║
╚══════════════════════════════════════════════════════════════╝

🚫 ERRORS:
─────────────────────────────────────────────────────────────

❌ Impact Score (customfield_10001)
Required field "Impact Score" (customfield_10001) not found in JPD project.

💡 How to fix:
1. Go to JPD Project Settings
2. Create custom field: "Impact Score"
3. Type: number
4. Add to project screens

─────────────────────────────────────────────────────────────
Sync cannot continue until all required fields are available.
─────────────────────────────────────────────────────────────

Discovering Field IDs

To find JPD custom field IDs, use the JPD API or debug logging:

# Enable debug mode
DEBUG=1 pnpm run dev -- --dry-run

Look for output like:

[DEBUG] Processing PROJ-1. Available fields: customfield_12345, customfield_67890, ...

Or use curl:

curl -u "your-email:your-api-token" \
"https://your-instance.atlassian.net/rest/api/3/issue/PROJ-1" \
| jq '.fields | keys'

Best Practices

1. Start with Required Fields Only

fields:
# Only validate fields you actually use in mappings
- id: "customfield_14377"
name: "Theme"
type: "multiselect"
required: true

2. Mark Optional Fields Appropriately

fields:
# Optional fields won't fail sync if null
- id: "customfield_14388"
name: "Notes"
type: "text"
required: false # ← Won't block sync if empty

3. Validate Before Production

# Test validation without making changes
pnpm run dev -- --dry-run

4. Document Your Fields

fields:
- id: "customfield_14376"
name: "Impact"
type: "number"
required: true
description: "RICE Impact score - How many people affected?"

Disabling Validation

If you don't want field validation, simply omit the fields section:

sync:
direction: bidirectional
jql: "project = MTT"

mappings:
- jpd: "fields.summary"
github: "title"

# No fields section = no validation

Troubleshooting

"No issues found in project"

Cause: Project is empty or JQL is incorrect
Fix: Create at least one issue in the project

"Field has type 'null' but expected 'text'"

Cause: Field exists but is empty on the sample issue
Fix: Either:

  • Populate the field on at least one issue
  • Mark the field as required: false

"Could not determine project key"

Cause: JQL doesn't include project = X clause
Fix: Add project key to JQL or set JPD_PROJECT_KEY env var

Future Enhancements

🚧 Automatic Field Creation (requires admin permissions)
🚧 Field Value Validation (ranges, patterns, etc.)
🚧 Custom Validation Rules (via functions)
🚧 Bulk Field Discovery (scan all issues)

Example: Complete Config

sync:
direction: bidirectional
jql: "project = MTT"

mappings:
- jpd: "fields.summary"
github: "title"

- jpd: "fields.customfield_14377[0].value"
github: "labels"
template: "{{fields.customfield_14377[0].value | slugify}}"

fields:
# Core RICE fields
- id: "customfield_14377"
name: "Theme"
type: "multiselect"
required: true
description: "Product theme"

- id: "customfield_14376"
name: "Impact"
type: "number"
required: true
description: "RICE Impact (0-10)"

- id: "customfield_14379"
name: "Reach"
type: "number"
required: true
description: "RICE Reach (users/quarter)"

- id: "customfield_14388"
name: "Notes"
type: "text"
required: false
description: "Optional notes"

See Also