Skip to content

Commit 6629101

Browse files
committed
Refactor: autoload, OOP cleanup, and comprehensive spec improvements
- Convert all require/require_relative to Ruby autoload - Extract Collection.parse_formats, ConfigExporter - Add SiteManifest models using lutaml-model - Improve Compiler: private validate_file_path, simplify options serialization - Clean up FatalCompilationError: pass message to super - Catch SystemExit from upstream gems, convert to FatalCompilationError - Remove all doubles/mocks from specs, use real instances - Fix font-related test failures with continue_without_fonts - Fix broken SystemExit test expectations in acceptance specs - Self-contained ietu fixture (inlined includes) - Update sample-itu fixture to avoid PDF font errors - Add collection rendering and config export specs
1 parent abbe135 commit 6629101

86 files changed

Lines changed: 7767 additions & 2199 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.codeclimate.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Initial content: https://docs.codeclimate.com/docs/default-analysis-configuration
2+
3+
# 'version' required to adjust maintainability checks
4+
version: "2"
5+
6+
checks:
7+
# argument-count:
8+
# enabled: true
9+
# config:
10+
# threshold: 4
11+
# complex-logic:
12+
# enabled: true
13+
# config:
14+
# threshold: 4
15+
# file-lines:
16+
# enabled: true
17+
# config:
18+
# threshold: 250
19+
# method-complexity:
20+
# enabled: true
21+
# config:
22+
# threshold: 5
23+
method-count:
24+
enabled: true
25+
config:
26+
# threshold: 20
27+
threshold: 50
28+
# method-lines:
29+
# enabled: true
30+
# config:
31+
# threshold: 25
32+
# nested-control-flow:
33+
# enabled: true
34+
# config:
35+
# threshold: 4
36+
# return-statements:
37+
# enabled: true
38+
# config:
39+
# threshold: 4
40+
# similar-code:
41+
# enabled: true
42+
# config:
43+
# threshold: #language-specific defaults. overrides affect all languages.
44+
# identical-code:
45+
# enabled: true
46+
# config:
47+
# threshold: #language-specific defaults. overrides affect all languages.
48+
49+
# plugins:
50+
# eslint:
51+
# enabled: true
52+
# channel: "eslint-6"
53+
# rubocop:
54+
# enabled: true
55+
# channel: "rubocop-0-79"
56+
57+
# exclude_patterns:
58+
# - "config/"
59+
# - "db/"
60+
# - "dist/"
61+
# - "features/"
62+
# - "**/node_modules/"
63+
# - "script/"
64+
# - "**/spec/"
65+
# - "**/test/"
66+
# - "**/tests/"
67+
# - "Tests/"
68+
# - "**/vendor/"
69+
# - "**/*_test.go"
70+
# - "**/*.d.ts"

.envrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use flake
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
ORGANISATION=metanorma
2-
DEPENDENT_REPOS="metanorma-docker metanorma.com packed-mn"
3-
TEMPLATE_REPOS="mn-templates-nist mn-templates-ietf mn-templates-ogc mn-templates-iso mn-templates-csd mn-templates-itu mn-templates-iec"
2+
DEPENDENT_REPOS="metanorma-docker metanorma-docker-private metanorma.com packed-mn"
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
name: docker-artifacts
2+
3+
on:
4+
repository_dispatch:
5+
types: [docker-published]
6+
pull_request:
7+
paths:
8+
- '.github/workflows/docker-artifacts.yml'
9+
workflow_dispatch:
10+
inputs:
11+
version:
12+
description: 'Version to extract Docker artifacts for (e.g., v1.2.3 or 1.2.3)'
13+
required: true
14+
type: string
15+
16+
permissions:
17+
contents: write
18+
19+
jobs:
20+
extract-docker-artifacts:
21+
runs-on: ubuntu-latest
22+
strategy:
23+
matrix:
24+
platform:
25+
- name: ruby
26+
image: metanorma/metanorma:latest
27+
bundle_path: /usr/local/bundle/Gemfile.lock
28+
- name: ubuntu
29+
image: metanorma/metanorma:ubuntu-latest
30+
bundle_path: /usr/local/bundle/Gemfile.lock
31+
- name: alpine
32+
image: metanorma/metanorma:alpine-latest
33+
bundle_path: /usr/local/bundle/Gemfile.lock
34+
fail-fast: false
35+
36+
steps:
37+
- name: Determine version
38+
id: version
39+
run: |
40+
if [ "${{ github.event_name }}" == "repository_dispatch" ]; then
41+
VERSION="${{ github.event.client_payload.version }}"
42+
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
43+
VERSION="${{ github.event.inputs.version }}"
44+
elif [ "${{ github.event_name }}" == "pull_request" ]; then
45+
# For PR testing, use a test version
46+
VERSION="v1.13.3"
47+
fi
48+
49+
# Normalize version (remove 'v' prefix if present)
50+
VERSION=${VERSION#v}
51+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
52+
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
53+
echo "Extracting Docker artifacts for version: ${VERSION}"
54+
55+
- name: Extract Gemfile.lock from ${{ matrix.platform.name }} container
56+
id: extract
57+
run: |
58+
PLATFORM="${{ matrix.platform.name }}"
59+
VERSION="${{ steps.version.outputs.version }}"
60+
61+
# Try version-specific tag first, then fall back to latest
62+
IMAGE_TAG="${{ matrix.platform.image }}"
63+
if [ "$PLATFORM" = "ruby" ]; then
64+
# For ruby platform, try version-specific tag
65+
VERSIONED_IMAGE="metanorma/metanorma:${{ steps.version.outputs.tag }}"
66+
if docker pull "$VERSIONED_IMAGE" 2>/dev/null; then
67+
IMAGE_TAG="$VERSIONED_IMAGE"
68+
echo "Using versioned image: $IMAGE_TAG"
69+
else
70+
echo "Versioned image not found, using latest: $IMAGE_TAG"
71+
fi
72+
fi
73+
74+
echo "Pulling Docker image: $IMAGE_TAG"
75+
if docker pull "$IMAGE_TAG"; then
76+
echo "Successfully pulled $IMAGE_TAG"
77+
78+
# Extract Gemfile.lock
79+
LOCK_FILE="metanorma-cli-${VERSION}-docker-${PLATFORM}.lock"
80+
echo "Extracting Gemfile.lock to: $LOCK_FILE"
81+
82+
if docker run --rm "$IMAGE_TAG" cat "${{ matrix.platform.bundle_path }}" > "$LOCK_FILE"; then
83+
echo "Successfully extracted Gemfile.lock"
84+
echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT
85+
echo "success=true" >> $GITHUB_OUTPUT
86+
87+
# Verify the file is not empty and contains expected content
88+
if [ -s "$LOCK_FILE" ] && grep -q "GEM" "$LOCK_FILE"; then
89+
echo "Gemfile.lock validation passed"
90+
echo "First 10 lines of extracted Gemfile.lock:"
91+
head -10 "$LOCK_FILE"
92+
else
93+
echo "❌ Gemfile.lock validation failed - file is empty or invalid"
94+
echo "success=false" >> $GITHUB_OUTPUT
95+
fi
96+
else
97+
echo "❌ Failed to extract Gemfile.lock from container"
98+
echo "success=false" >> $GITHUB_OUTPUT
99+
fi
100+
else
101+
echo "❌ Failed to pull Docker image: $IMAGE_TAG"
102+
echo "success=false" >> $GITHUB_OUTPUT
103+
fi
104+
105+
- name: Generate checksum for ${{ matrix.platform.name }}
106+
if: steps.extract.outputs.success == 'true'
107+
run: |
108+
LOCK_FILE="${{ steps.extract.outputs.lock_file }}"
109+
sha256sum "$LOCK_FILE" > "${LOCK_FILE}.sha256"
110+
echo "Generated checksum for $LOCK_FILE:"
111+
cat "${LOCK_FILE}.sha256"
112+
113+
- name: Upload ${{ matrix.platform.name }} artifacts to release
114+
if: steps.extract.outputs.success == 'true' && github.event_name != 'pull_request'
115+
uses: softprops/action-gh-release@v2
116+
with:
117+
tag_name: ${{ steps.version.outputs.tag }}
118+
files: |
119+
${{ steps.extract.outputs.lock_file }}
120+
${{ steps.extract.outputs.lock_file }}.sha256
121+
122+
- name: Platform summary
123+
run: |
124+
if [ "${{ steps.extract.outputs.success }}" = "true" ]; then
125+
if [ "${{ github.event_name }}" = "pull_request" ]; then
126+
echo "🧪 ${{ matrix.platform.name }} platform artifacts built but not uploaded (PR mode)"
127+
else
128+
echo "✅ ${{ matrix.platform.name }} platform artifacts completed successfully!"
129+
echo "📦 Uploaded: ${{ steps.extract.outputs.lock_file }}"
130+
fi
131+
else
132+
echo "❌ ${{ matrix.platform.name }} platform artifacts failed"
133+
echo "This may be expected if the Docker image is not yet available"
134+
fi
135+
136+
extract-windows-artifacts:
137+
runs-on: windows-latest
138+
steps:
139+
- name: Determine version
140+
id: version
141+
run: |
142+
if ("${{ github.event_name }}" -eq "repository_dispatch") {
143+
$VERSION = "${{ github.event.client_payload.version }}"
144+
} elseif ("${{ github.event_name }}" -eq "workflow_dispatch") {
145+
$VERSION = "${{ github.event.inputs.version }}"
146+
} elseif ("${{ github.event_name }}" -eq "pull_request") {
147+
# For PR testing, use a test version
148+
$VERSION = "v1.13.3"
149+
}
150+
151+
# Normalize version (remove 'v' prefix if present)
152+
$VERSION = $VERSION -replace '^v', ''
153+
echo "version=$VERSION" >> $env:GITHUB_OUTPUT
154+
echo "tag=v$VERSION" >> $env:GITHUB_OUTPUT
155+
echo "Extracting Windows Docker artifacts for version: $VERSION"
156+
157+
- name: Extract Gemfile.lock from Windows container
158+
id: extract
159+
run: |
160+
$VERSION = "${{ steps.version.outputs.version }}"
161+
$IMAGE_TAG = "metanorma/metanorma:windows-ltsc2022"
162+
163+
Write-Host "Pulling Windows Docker image: $IMAGE_TAG"
164+
try {
165+
docker pull $IMAGE_TAG
166+
Write-Host "Successfully pulled $IMAGE_TAG"
167+
168+
# Extract Gemfile.lock
169+
$LOCK_FILE = "metanorma-cli-$VERSION-docker-windows.lock"
170+
Write-Host "Extracting Gemfile.lock to: $LOCK_FILE"
171+
172+
# Try multiple possible locations for Gemfile.lock
173+
$POSSIBLE_PATHS = @(
174+
"C:\metanorma\Gemfile.lock",
175+
"C:\setup\Gemfile.lock",
176+
"C:\usr\local\bundle\Gemfile.lock"
177+
)
178+
179+
$SUCCESS = $false
180+
foreach ($PATH in $POSSIBLE_PATHS) {
181+
Write-Host "Trying path: $PATH"
182+
try {
183+
docker run --rm $IMAGE_TAG cmd /c "type `"$PATH`"" | Out-File -FilePath $LOCK_FILE -Encoding UTF8
184+
if (Test-Path $LOCK_FILE -PathType Leaf) {
185+
$content = Get-Content $LOCK_FILE -Raw
186+
if ($content -and $content.Contains("GEM")) {
187+
Write-Host "✅ Successfully extracted Gemfile.lock from: $PATH"
188+
$SUCCESS = $true
189+
break
190+
}
191+
}
192+
} catch {
193+
Write-Host "❌ Failed to extract from: $PATH"
194+
}
195+
}
196+
197+
if (-not $SUCCESS) {
198+
Write-Host "❌ Could not find Gemfile.lock in any expected location"
199+
# List directory contents to help debug
200+
Write-Host "Listing C:\ contents recursively:"
201+
docker run --rm $IMAGE_TAG cmd /c "dir C:\ /s /b | findstr /i gemfile"
202+
Write-Host "Searching for all Gemfile.lock files:"
203+
docker run --rm $IMAGE_TAG cmd /c "dir C:\*.lock /s /b"
204+
Write-Host "Searching for all Gemfile files:"
205+
docker run --rm $IMAGE_TAG cmd /c "dir C:\*Gemfile* /s /b"
206+
Write-Host "Listing C:\metanorma contents:"
207+
docker run --rm $IMAGE_TAG cmd /c "if exist C:\metanorma (dir C:\metanorma /b) else (echo Directory C:\metanorma does not exist)"
208+
Write-Host "Listing C:\setup contents:"
209+
docker run --rm $IMAGE_TAG cmd /c "if exist C:\setup (dir C:\setup /b) else (echo Directory C:\setup does not exist)"
210+
}
211+
212+
if (Test-Path $LOCK_FILE -PathType Leaf) {
213+
$content = Get-Content $LOCK_FILE -Raw
214+
if ($content -and $content.Contains("GEM")) {
215+
Write-Host "Successfully extracted and validated Gemfile.lock"
216+
echo "lock_file=$LOCK_FILE" >> $env:GITHUB_OUTPUT
217+
echo "success=true" >> $env:GITHUB_OUTPUT
218+
219+
Write-Host "First 10 lines of extracted Gemfile.lock:"
220+
Get-Content $LOCK_FILE | Select-Object -First 10
221+
} else {
222+
Write-Host "❌ Gemfile.lock validation failed - file is empty or invalid"
223+
echo "success=false" >> $env:GITHUB_OUTPUT
224+
}
225+
} else {
226+
Write-Host "❌ Failed to extract Gemfile.lock from container"
227+
echo "success=false" >> $env:GITHUB_OUTPUT
228+
}
229+
} catch {
230+
Write-Host "❌ Failed to pull or extract from Windows Docker image: $_"
231+
echo "success=false" >> $env:GITHUB_OUTPUT
232+
}
233+
234+
- name: Generate checksum for Windows
235+
if: steps.extract.outputs.success == 'true'
236+
run: |
237+
$LOCK_FILE = "${{ steps.extract.outputs.lock_file }}"
238+
$hash = Get-FileHash -Path $LOCK_FILE -Algorithm SHA256
239+
"$($hash.Hash.ToLower()) $LOCK_FILE" | Out-File -FilePath "$LOCK_FILE.sha256" -Encoding ASCII
240+
Write-Host "Generated checksum for $LOCK_FILE:"
241+
Get-Content "$LOCK_FILE.sha256"
242+
243+
- name: Upload Windows artifacts to release
244+
if: steps.extract.outputs.success == 'true' && github.event_name != 'pull_request'
245+
uses: softprops/action-gh-release@v2
246+
with:
247+
tag_name: ${{ steps.version.outputs.tag }}
248+
files: |
249+
${{ steps.extract.outputs.lock_file }}
250+
${{ steps.extract.outputs.lock_file }}.sha256
251+
252+
- name: Windows summary
253+
run: |
254+
if ("${{ steps.extract.outputs.success }}" -eq "true") {
255+
if ("${{ github.event_name }}" -eq "pull_request") {
256+
Write-Host "🧪 Windows platform artifacts built but not uploaded (PR mode)"
257+
} else {
258+
Write-Host "✅ Windows platform artifacts completed successfully!"
259+
Write-Host "📦 Uploaded: ${{ steps.extract.outputs.lock_file }}"
260+
}
261+
} else {
262+
Write-Host "❌ Windows platform artifacts failed"
263+
Write-Host "This may be expected if the Windows Docker image is not yet available"
264+
}
265+
266+
summary:
267+
runs-on: ubuntu-latest
268+
needs: [extract-docker-artifacts, extract-windows-artifacts]
269+
if: always()
270+
steps:
271+
- name: Determine version
272+
id: version
273+
run: |
274+
if [ "${{ github.event_name }}" == "repository_dispatch" ]; then
275+
VERSION="${{ github.event.client_payload.version }}"
276+
elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
277+
VERSION="${{ github.event.inputs.version }}"
278+
elif [ "${{ github.event_name }}" == "pull_request" ]; then
279+
# For PR testing, use a test version
280+
VERSION="v1.13.3"
281+
fi
282+
283+
# Normalize version (remove 'v' prefix if present)
284+
VERSION=${VERSION#v}
285+
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
286+
287+
- name: Final summary
288+
run: |
289+
echo "🐳 Docker artifacts extraction completed for version: ${{ steps.version.outputs.tag }}"
290+
echo "🔗 Check the release at: https://github.com/metanorma/metanorma-cli/releases/tag/${{ steps.version.outputs.tag }}"
291+
echo ""
292+
echo "Expected artifacts:"
293+
echo " • metanorma-cli-*-docker-ruby.lock"
294+
echo " • metanorma-cli-*-docker-ubuntu.lock"
295+
echo " • metanorma-cli-*-docker-alpine.lock"
296+
echo " • metanorma-cli-*-docker-windows.lock"
297+
echo " • SHA256 checksums for all lock files"
298+
echo ""
299+
echo "Note: Some artifacts may be missing if corresponding Docker images are not yet available."

0 commit comments

Comments
 (0)