Skip to content
Draft
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
32 changes: 32 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "Copilot Setup Steps"

# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
on:
workflow_dispatch:
pull_request:
branches: [main]
paths:
- .github/workflows/copilot-setup-steps.yml

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest

# Set the permissions to the lowest permissions possible needed for your steps.
# Copilot will be given its own token for its operations.
permissions:
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
contents: read

# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Checkout code
uses: actions/checkout@v5

- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v2.x
41 changes: 41 additions & 0 deletions .github/workflows/validate-conformance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Validate Conformance Report

on:
pull_request:
paths:
- 'data/conformance.json'
- 'scripts/generate-conformance-report.ts'
- 'CONFORMANCE.md'
push:
branches:
- main
paths:
- 'data/conformance.json'
- 'scripts/generate-conformance-report.ts'

jobs:
validate:
runs-on: ubuntu-latest

permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v2.x

- name: Generate conformance report
run: deno task generate

- name: Check if CONFORMANCE.md is up to date
run: |
if ! git diff --exit-code CONFORMANCE.md; then
echo "Error: CONFORMANCE.md is not up to date with conformance.json"
echo "Please run 'deno task generate' and commit the changes"
exit 1
fi
90 changes: 90 additions & 0 deletions .github/workflows/validate-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Validate Documentation

on:
pull_request:
paths:
- '**.md'
push:
branches:
- main
paths:
- '**.md'

jobs:
validate-links:
runs-on: ubuntu-latest

permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Check for broken relative links
run: |
echo "Checking for broken relative links in markdown files..."

# Function to check if a file exists
check_link() {
local file="$1"
local link="$2"
local dir=$(dirname "$file")

# Skip external links
if [[ "$link" =~ ^https?:// ]]; then
return 0
fi

# Skip anchors only
if [[ "$link" =~ ^# ]]; then
return 0
fi

# Remove anchor from link
local path="${link%%#*}"

# Resolve relative path
local full_path="$dir/$path"

if [ ! -e "$full_path" ]; then
echo "::error file=$file::Broken link found: $link (resolved to $full_path)"
return 1
fi
return 0
}

error_count=0

# Find all markdown files and check their links
while IFS= read -r file; do
# Extract markdown links [text](url)
grep -oP '\[([^\]]+)\]\(([^\)]+)\)' "$file" | while IFS= read -r match; do
link=$(echo "$match" | sed -n 's/.*](\([^)]*\)).*/\1/p')
if ! check_link "$file" "$link"; then
error_count=$((error_count + 1))
fi
done
done < <(find . -name "*.md" -not -path "./.git/*" -not -path "./node_modules/*")

if [ $error_count -gt 0 ]; then
echo "Found $error_count broken link(s)"
exit 1
fi

echo "✓ No broken links found"

markdown-lint:
runs-on: ubuntu-latest

permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Run markdown lint
uses: DavidAnson/markdownlint-cli2-action@v18
with:
globs: '**/*.md'
19 changes: 19 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"default": true,
"MD007": false,
"MD009": false,
"MD012": false,
"MD013": false,
"MD022": false,
"MD026": false,
"MD030": false,
"MD031": false,
"MD032": false,
"MD033": false,
"MD034": false,
"MD036": false,
"MD041": false,
"MD047": false,
"MD052": false,
"MD060": false
}
4 changes: 2 additions & 2 deletions CONFORMANCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ This table shows the percentage of the 17 libraries listed below that meet diffe
| **Java Libraries** | **OCPS 1.0** | **OCPS 1.1** | **OCPS 1.2** | **OCPS 1.3** | **OCPS 1.4** | **Notes** |
| :--- | :---: | :---: | :---: | :---: | :---: | :--- |
| **Spring Framework (`@Scheduled`)** | 🟡 | ❌ | ✅ | ✅ | 🟡 | Supports seconds, `L`, `W`, `#`. Uses `AND` logic for date fields. `?` is a wildcard. No nicknames. [7] |
| **Quartz** | 🟡 | ❌ | ✅ | ✅ | 🟡 | Original source for `L`, `W`, `#`. Does not allow combining dom ad dow, and but requires `?` to disambiguate date fields. No nicknames. [8][9] |
| **Quartz** | 🟡 | ❌ | ✅ | ✅ | 🟡 | Original source for `L`, `W`, `#`. Does not allow combining dom and dow, but requires `?` to disambiguate date fields. No nicknames. [8][9] |

### .NET Libraries

Expand Down Expand Up @@ -128,6 +128,6 @@ This table shows the percentage of the 17 libraries listed below that meet diffe


---
*This document is automatically generated from [data/conformance.json](./data/conformance.json) on 2025-10-28.*
*This document is automatically generated from [data/conformance.json](./data/conformance.json) on 2025-11-19.*

*This table is based on analysis of official documentation and community knowledge. For the most accurate details, please refer to the documentation of the respective libraries.*
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,16 @@ Changes to this **README** should always be submitted as a pull request.

The Implementation Conformance Matrix is automatically generated from the `data/conformance.json` file. To propose changes, please edit `data/conformance.json` and submit a pull request.

If you wish to regenerate the `CONFORMANCE.md` file locally to preview your changes, you can run the generation script. This requires Deno to be installed.
If you wish to regenerate the `CONFORMANCE.md` file locally to preview your changes, you can run the generation script. This requires [Deno](https://deno.land/) to be installed.

**From the root of the repository:**
`cd scripts && deno run -A generate-conformance-report.ts`
**Using the deno task (recommended):**
```bash
deno task generate
```

**Or directly:**
```bash
cd scripts && deno run -A generate-conformance-report.ts
```

**Note:** Pull requests that modify `data/conformance.json` will be automatically validated by GitHub Actions to ensure `CONFORMANCE.md` is kept in sync.
2 changes: 1 addition & 1 deletion data/conformance.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"name": "Java Libraries",
"items": [
{ "name": "Spring Framework (`@Scheduled`)", "compliance": { "1.0": "partial", "1.1": "none", "1.2": "full", "1.3": "full", "1.4": "partial" }, "notes": "Supports seconds, `L`, `W`, `#`. Uses `AND` logic for date fields. `?` is a wildcard. No nicknames.", "references": [7] },
{ "name": "Quartz", "compliance": { "1.0": "partial", "1.1": "none", "1.2": "full", "1.3": "full", "1.4": "partial" }, "notes": "Original source for `L`, `W`, `#`. Does not allow combining dom ad dow, and but requires `?` to disambiguate date fields. No nicknames.", "references": [8, 9] }
{ "name": "Quartz", "compliance": { "1.0": "partial", "1.1": "none", "1.2": "full", "1.3": "full", "1.4": "partial" }, "notes": "Original source for `L`, `W`, `#`. Does not allow combining dom and dow, but requires `?` to disambiguate date fields. No nicknames.", "references": [8, 9] }
]
},
{
Expand Down
12 changes: 12 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"tasks": {
"generate": "cd scripts && deno run -A generate-conformance-report.ts",
"generate:check": "cd scripts && deno run -A generate-conformance-report.ts && cd .. && git diff --exit-code CONFORMANCE.md"
},
"fmt": {
"exclude": ["data/", "CONFORMANCE.md"]
},
"lint": {
"exclude": ["data/", "CONFORMANCE.md"]
}
}
23 changes: 21 additions & 2 deletions scripts/generate-conformance-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,31 @@ interface ConformanceData {
async function generateConformanceReport() {
try {
// 1. Read and parse the JSON data
console.log('Reading conformance.json...');
const jsonText = await Deno.readTextFile('../data/conformance.json');
const data: ConformanceData = JSON.parse(jsonText);

let data: ConformanceData;
try {
data = JSON.parse(jsonText);
} catch (parseError) {
console.error('Failed to parse conformance.json:', parseError);
Deno.exit(1);
}

// Validate data structure
if (!data.legend || !data.categories || !data.references) {
console.error('Invalid conformance.json structure: missing required fields');
Deno.exit(1);
}

const versions = getVersions(data);
const libraries = getLibraries(data);
const usedReferenceIds = getUsedReferenceIds(data);

console.log(`Found ${versions.length} versions and ${libraries.length} libraries`);

// 2. Generate dynamic parts of the Markdown
console.log('Generating report sections...');
const legend = generateLegend(data.legend);
const adoptionSummary = generateAdoptionSummary(versions, libraries);
const tables = generateAllTables(data.categories, versions, data.legend);
Expand All @@ -98,11 +115,13 @@ async function generateConformanceReport() {
.trim();

// 4. Write the output file
console.log('Writing CONFORMANCE.md...');
await Deno.writeTextFile('../CONFORMANCE.md', md);
console.log('Successfully generated CONFORMANCE.md');
console.log('Successfully generated CONFORMANCE.md');

} catch (error) {
console.error('Error generating conformance report:', error);
Deno.exit(1);
}
}

Expand Down
Loading