Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
35c4b47
chore: establish a basic structure for document generation
rjaegers Jun 23, 2025
971710e
chore: playing around with location and granularity
rjaegers Jun 23, 2025
4781fa6
chore: add gherkin extraction
rjaegers Jun 24, 2025
e4ec3d3
Merge branch 'main' into feature/document-generation
rjaegers Jul 22, 2025
cd08647
Merge branch 'main' into feature/document-generation
rjaegers Aug 21, 2025
f88a6f0
Merge branch 'main' into feature/document-generation
rjaegers Sep 9, 2025
ca61782
docs: generate requirements document
rjaegers Sep 24, 2025
e3cc660
fix: don't use sudo in workflows
rjaegers Sep 24, 2025
176a0f0
fix: allow sudo in workflow that needs it
rjaegers Sep 24, 2025
ada3cac
ci: install missing package
rjaegers Sep 24, 2025
c8df85b
Apply suggestions from code review
rjaegers Sep 25, 2025
e75b5fc
Merge branch 'main' into feature/document-generation
rjaegers Sep 25, 2025
ac7263d
docs: generate nicer PDF
rjaegers Sep 25, 2025
c4f4768
Merge branch 'feature/document-generation' of https://github.com/phil…
rjaegers Sep 25, 2025
9c37fe1
chore: correct workflow syntax
rjaegers Sep 25, 2025
becc991
chore: minor refactor to workflow
rjaegers Sep 25, 2025
a11b967
chore: pin pip dependencies
rjaegers Sep 25, 2025
8caaba2
docs: make the pdf more appealing
rjaegers Sep 25, 2025
e51eaef
chore: refactor gherkin to sbdl workflow
rjaegers Sep 25, 2025
34621e0
chore: refactor requirement structure
rjaegers Sep 25, 2025
de87a42
chore: enable listings code highlighter
rjaegers Sep 25, 2025
aac0e2e
Merge branch 'main' into feature/document-generation-additions
rjaegers Sep 25, 2025
db8cafb
docs: add eisvogel front-matter
rjaegers Sep 25, 2025
2cb5a4a
Merge branch 'feature/document-generation-additions' of https://githu…
rjaegers Sep 25, 2025
6e07d15
docs: update to front-matter config
rjaegers Sep 25, 2025
f2e6e60
docs: add more requirements
rjaegers Sep 25, 2025
bbc02bf
docs: add a toc
rjaegers Sep 25, 2025
cdf9a70
docs: extend requirements
rjaegers Sep 29, 2025
9e239d1
chore: refactor gherkin to sbdl
rjaegers Sep 29, 2025
1d9340b
Merge branch 'main' into feature/document-generation-additions
rjaegers Sep 30, 2025
8ef18fc
Update docs/templates/software-requirements-specification.md.j2
rjaegers Oct 1, 2025
71087b5
Merge branch 'main' into feature/document-generation-additions
rjaegers Oct 1, 2025
5a91818
chore: refactor for testability
rjaegers Oct 1, 2025
8ff7a45
chore: extend the urllib3 ignores with one month
rjaegers Oct 1, 2025
b0fd257
chore: update linter settings
rjaegers Oct 1, 2025
c9113e3
chore: add missing import
rjaegers Oct 2, 2025
6b3eefb
chore: add *.pyc to gitignore
rjaegers Oct 2, 2025
59d76ba
chore: add documents to release upload
rjaegers Oct 2, 2025
446a5fc
docs: minor cosmetic changes
rjaegers Oct 2, 2025
72534db
chore: processed review comments
rjaegers Oct 4, 2025
76a665e
chore: correct/extend lychee scope
rjaegers Oct 4, 2025
5fe9db4
Update docs/support/gherkin_sbdl_converter.py
rjaegers Oct 4, 2025
fe3f8ec
Update .mega-linter.yml
rjaegers Oct 4, 2025
893436e
style: add newline between classes
rjaegers Oct 4, 2025
0336d46
Merge branch 'main' into feature/document-generation-additions
rjaegers Oct 5, 2025
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
2 changes: 1 addition & 1 deletion .github/linters/.gherkin-lintrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"no-duplicate-tags": "on",
"no-empty-background": "on",
"no-empty-file": "on",
"no-files-without-scenarios": "on",
"no-files-without-scenarios": "off",
"no-multiple-empty-lines": "on",
"no-partially-commented-tag-lines": "on",
"no-scenario-outlines-without-examples": "on",
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ jobs:
GH_TOKEN: ${{ github.token }}
REPOSITORY_OWNER: ${{ github.repository_owner }}
REPOSITORY_NAME: ${{ github.event.repository.name }}
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
with:
pattern: documents
- name: Upload documents to release
run: |
set -Eeuo pipefail
gh release upload "${REF_NAME}" ./*.pdf
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ github.token }}
- name: Update package details in release
run: |
set -Eeuo pipefail
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/wc-document-generation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ jobs:
set -Eeuo pipefail
sudo apt-get update && sudo apt-get install --no-install-recommends -y plantuml
python -m pip install gherkin-official==35.1.0 sbdl==1.16.4
- name: Generate requirements document
- name: Generate SRS document
run: |
set -Eeuo pipefail
python docs/support/gherkin-to-csv.py test/cpp/features/*.feature
python -m csv-to-sbdl --identifier 0 --description 1 --skipheader rules.csv
sbdl -m template-fill --template docs/templates/requirements.template.md output.sbdl > requirements.md
python docs/support/gherkin-to-sbdl.py test/cpp/features/*.feature
sbdl -m template-fill --template docs/templates/software-requirements-specification.md.j2 output.sbdl > software-requirements-specification.md
- uses: docker://pandoc/extra:3.7.0@sha256:a703d335fa237f8fc3303329d87e2555dca5187930da38bfa9010fa4e690933a
with:
args: --template eisvogel --output requirements.pdf requirements.md
args: --template eisvogel --listings --number-sections --output software-requirements-specification.pdf software-requirements-specification.md
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: documents
path: requirements.pdf
path: "*.pdf"
retention-days: 2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ test-results/
.env
*.profdata
*.profraw
*.pyc
**/playwright/.auth/user.json
CMakeUserPresets.json
3 changes: 2 additions & 1 deletion .mega-linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ ENABLE:
- SPELL
- YAML
DISABLE_LINTERS:
- MARKDOWN_MARKDOWN_LINK_CHECK
- REPOSITORY_DEVSKIM
- REPOSITORY_DUSTILOCK
- REPOSITORY_KICS
Expand All @@ -18,6 +17,8 @@ DISABLE_LINTERS:
SARIF_REPORTER: true
PRINT_ALPACA: false
SHOW_SKIPPED_LINTERS: false
SPELL_LYCHEE_FILE_EXTENSIONS:
[".feature", ".json", ".md", ".md.j2", ".txt", ".yaml", ".yml"]
FILTER_REGEX_EXCLUDE: (CHANGELOG.md|package-lock.json)
# tasks.json is wrongfully matched against another schema,
# and schemas for .vscode/[tasks.json|launch.json] are built
Expand Down
75 changes: 0 additions & 75 deletions docs/support/gherkin-to-csv.py

This file was deleted.

39 changes: 39 additions & 0 deletions docs/support/gherkin-to-sbdl.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env python3

import argparse
import os
import sys

from gherkin_mapping_config import FEATURE_RULE_CONFIG, FEATURE_RULE_SCENARIO_CONFIG
from gherkin_sbdl_converter import GherkinConverter

def main():
configs = {
'feature-rule': FEATURE_RULE_CONFIG,
'feature-rule-scenario': FEATURE_RULE_SCENARIO_CONFIG
}

parser = argparse.ArgumentParser(description='Configurable Gherkin to SBDL converter')
parser.add_argument('feature_files', nargs='+', help='Paths to feature files')
parser.add_argument('--output', '-o', default='output.sbdl', help='Output SBDL file')
parser.add_argument('--config', choices=configs.keys(),
default='feature-rule', help='Conversion configuration preset')

args = parser.parse_args()
config = configs[args.config]
converter = GherkinConverter(config)
gherkin_elements = []

for feature_path in args.feature_files:
if os.path.isfile(feature_path):
print(f"Processing {feature_path}")
elements = converter.extract_from_feature_file(feature_path)
gherkin_elements.extend(elements)
else:
print(f"File not found: {feature_path}", file=sys.stderr)

converter.write_sbdl_output(gherkin_elements, args.output)
print(f"Extracted {len(gherkin_elements)} elements to {args.output}")

if __name__ == '__main__':
main()
106 changes: 106 additions & 0 deletions docs/support/gherkin_mapping_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#!/usr/bin/env python3

"""
Configuration-driven Gherkin to SBDL mapping with flexible hierarchy support.
"""

from dataclasses import dataclass
from typing import Dict, List, Optional, Union
from enum import Enum

class GherkinElementType(Enum):
"""Supported Gherkin element types for conversion."""
FEATURE = "feature"
RULE = "rule"
SCENARIO = "scenario"
SCENARIO_OUTLINE = "scenario_outline"
EXAMPLE = "example"
BACKGROUND = "background"

class SBDLElementType(Enum):
"""Supported SBDL element types for mapping."""
REQUIREMENT = "requirement"
ASPECT = "aspect"
USECASE = "usecase"
DEFINITION = "definition"
TEST = "test"

@dataclass
class HierarchyMapping:
"""Configuration for mapping Gherkin elements to SBDL with document hierarchy."""
gherkin_type: GherkinElementType
sbdl_type: SBDLElementType

@dataclass
class ConversionConfig:
"""Complete configuration for Gherkin to SBDL conversion."""
hierarchy_mappings: List[HierarchyMapping]

def get_mapping_for_type(self, gherkin_type: GherkinElementType) -> Optional[HierarchyMapping]:
"""Get the hierarchy mapping for a specific Gherkin element type."""
for mapping in self.hierarchy_mappings:
if mapping.gherkin_type == gherkin_type:
return mapping
return None

# Predefined configurations for different use cases

# Current Configuration (Feature -> Rule mapping)
FEATURE_RULE_CONFIG = ConversionConfig(
hierarchy_mappings=[
HierarchyMapping(
gherkin_type=GherkinElementType.FEATURE,
sbdl_type=SBDLElementType.REQUIREMENT
),
HierarchyMapping(
gherkin_type=GherkinElementType.RULE,
sbdl_type=SBDLElementType.REQUIREMENT
)
]
)

# Extended Configuration (Feature -> Rule -> Scenario mapping)
FEATURE_RULE_SCENARIO_CONFIG = ConversionConfig(
hierarchy_mappings=[
HierarchyMapping(
gherkin_type=GherkinElementType.FEATURE,
sbdl_type=SBDLElementType.ASPECT
),
HierarchyMapping(
gherkin_type=GherkinElementType.RULE,
sbdl_type=SBDLElementType.REQUIREMENT
),
HierarchyMapping(
gherkin_type=GherkinElementType.SCENARIO,
sbdl_type=SBDLElementType.TEST
)
]
)

# Flat Configuration (All as requirements at same level)
FLAT_CONFIG = ConversionConfig(
hierarchy_mappings=[
HierarchyMapping(
gherkin_type=GherkinElementType.FEATURE,
sbdl_type=SBDLElementType.REQUIREMENT
),
HierarchyMapping(
gherkin_type=GherkinElementType.RULE,
sbdl_type=SBDLElementType.REQUIREMENT
)
]
)

# Use Case Focused Configuration
USECASE_CONFIG = ConversionConfig(
hierarchy_mappings=[
HierarchyMapping(
gherkin_type=GherkinElementType.FEATURE,
sbdl_type=SBDLElementType.USECASE
),
HierarchyMapping(
gherkin_type=GherkinElementType.SCENARIO,
sbdl_type=SBDLElementType.USECASE
)
]
)
Loading
Loading