Skip to content

Commit 833964a

Browse files
Merge pull request #474 from immutable/chore/sample-app-tutorial
chore: sample app tutorial automation
2 parents ea39962 + 797e2a5 commit 833964a

File tree

19 files changed

+1695
-66
lines changed

19 files changed

+1695
-66
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/usr/bin/env node
2+
3+
'use strict';
4+
5+
const fs = require('fs');
6+
const path = require('path');
7+
8+
// Configuration
9+
const PASSPORT_ROOT = './sample/Assets/Scripts/Passport';
10+
const TUTORIALS_DIR = path.join(PASSPORT_ROOT, '_tutorials');
11+
const OUTPUT_DIR = './_parsed';
12+
const OUTPUT_FILE = path.join(OUTPUT_DIR, 'passport-features.json');
13+
const FEATURES_JSON_PATH = path.join(PASSPORT_ROOT, 'features.json');
14+
15+
// Ensure output directory exists
16+
try {
17+
if (!fs.existsSync(OUTPUT_DIR)) {
18+
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
19+
}
20+
} catch (error) {
21+
console.error(`Error creating output directory: ${error.message}`);
22+
process.exit(1);
23+
}
24+
25+
console.log('Processing Passport features metadata...');
26+
27+
// Load features.json to get feature groups and their features
28+
let featureGroups = {};
29+
try {
30+
const featuresContent = fs.readFileSync(FEATURES_JSON_PATH, 'utf8');
31+
const featuresJson = JSON.parse(featuresContent);
32+
featureGroups = featuresJson.features || {};
33+
} catch (error) {
34+
console.error(`Error reading features.json: ${error.message}`);
35+
process.exit(1);
36+
}
37+
38+
// Find all feature group directories in _tutorials
39+
const findFeatureGroupDirectories = () => {
40+
const featureGroupDirs = [];
41+
42+
if (!fs.existsSync(TUTORIALS_DIR)) {
43+
console.warn(`Tutorials directory does not exist: ${TUTORIALS_DIR}`);
44+
return featureGroupDirs;
45+
}
46+
47+
try {
48+
const dirs = fs.readdirSync(TUTORIALS_DIR, { withFileTypes: true });
49+
50+
dirs.forEach((dirent) => {
51+
if (dirent.isDirectory()) {
52+
featureGroupDirs.push(path.join(TUTORIALS_DIR, dirent.name));
53+
}
54+
});
55+
} catch (err) {
56+
console.warn(`Error reading tutorials directory ${TUTORIALS_DIR}: ${err.message}`);
57+
}
58+
59+
return featureGroupDirs;
60+
};
61+
62+
// Process metadata files
63+
const processFeatureGroups = (featureGroupDirs) => {
64+
const featuresObject = {};
65+
66+
featureGroupDirs.forEach((groupDir) => {
67+
const groupName = path.basename(groupDir);
68+
console.log(`Processing feature group: ${groupName}`);
69+
70+
// Check if this group exists in features.json (case-insensitive)
71+
const matchingGroup = Object.keys(featureGroups).find(
72+
key => key.toLowerCase() === groupName.toLowerCase()
73+
);
74+
75+
if (!matchingGroup) {
76+
console.warn(`Feature group ${groupName} not found in features.json, skipping`);
77+
return;
78+
}
79+
80+
// Path to metadata.json in this feature group directory
81+
const metadataPath = path.join(groupDir, 'metadata.json');
82+
if (!fs.existsSync(metadataPath)) {
83+
console.warn(`No metadata.json found for feature group ${groupName} in ${groupDir}`);
84+
return;
85+
}
86+
87+
// Path to tutorial.md in this feature group directory
88+
const tutorialPath = path.join(groupDir, 'tutorial.md');
89+
const tutorialExists = fs.existsSync(tutorialPath);
90+
91+
// Use the folder name directly as the feature key
92+
const featureKey = groupName;
93+
94+
if (!featureKey) {
95+
console.warn(`Generated empty feature key for ${groupDir}, skipping`);
96+
return;
97+
}
98+
99+
const tutorialFile = tutorialExists ? `${featureKey}.md` : null;
100+
101+
if (!tutorialExists) {
102+
console.warn(`No tutorial.md found for feature group ${groupName} in ${groupDir}`);
103+
}
104+
105+
// Read and process metadata
106+
try {
107+
const metadataContent = fs.readFileSync(metadataPath, 'utf8');
108+
const metadata = JSON.parse(metadataContent);
109+
110+
// Add additional fields
111+
metadata.title = metadata.title || matchingGroup;
112+
metadata.sidebar_order = metadata.sidebar_order || 0;
113+
metadata.deprecated = metadata.deprecated || false;
114+
115+
// Add feature group information
116+
metadata.feature_group = matchingGroup;
117+
metadata.features = Object.keys(featureGroups[matchingGroup] || {});
118+
119+
// Create the feature entry
120+
featuresObject[featureKey] = {
121+
tutorial: tutorialFile,
122+
metadata: metadata
123+
};
124+
} catch (error) {
125+
console.error(`Error processing metadata file ${metadataPath}: ${error.message}`);
126+
}
127+
});
128+
129+
return featuresObject;
130+
};
131+
132+
try {
133+
// Main execution
134+
const featureGroupDirs = findFeatureGroupDirectories();
135+
136+
if (featureGroupDirs.length === 0) {
137+
console.warn('No feature group directories found. Output file will be empty.');
138+
}
139+
140+
const features = processFeatureGroups(featureGroupDirs);
141+
142+
// Create the final passport-features.json
143+
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(features, null, 2));
144+
console.log(`Created ${OUTPUT_FILE}`);
145+
} catch (error) {
146+
console.error(`Fatal error: ${error.message}`);
147+
process.exit(1);
148+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/bash
2+
3+
set -e
4+
set -x
5+
6+
# Directory where docs repo is cloned
7+
DOCS_REPO_DIR="${CLONE_DIR:-"./imx-docs"}"
8+
9+
# Root of the Passport features
10+
PASSPORT_ROOT="./sample/Assets/Scripts/Passport"
11+
TUTORIALS_DIR="${PASSPORT_ROOT}/_tutorials"
12+
13+
echo "Processing Passport tutorials..."
14+
15+
# Load features.json to get feature groups
16+
FEATURES_JSON="${PASSPORT_ROOT}/features.json"
17+
if [ ! -f "${FEATURES_JSON}" ]; then
18+
echo "Error: features.json not found at ${FEATURES_JSON}"
19+
exit 1
20+
fi
21+
22+
# Create _tutorials directory in docs repo
23+
DOCS_TUTORIALS_DIR="${DOCS_REPO_DIR}/docs/main/example/zkEVM/unity/passport-examples/_tutorials"
24+
mkdir -p "${DOCS_TUTORIALS_DIR}"
25+
26+
# Check if _tutorials directory exists
27+
if [ ! -d "${TUTORIALS_DIR}" ]; then
28+
echo "Warning: _tutorials directory not found at ${TUTORIALS_DIR}"
29+
else
30+
# Process each feature group directory in _tutorials
31+
find "${TUTORIALS_DIR}" -mindepth 1 -maxdepth 1 -type d -print0 | while IFS= read -r -d '' GROUP_DIR; do
32+
echo "Processing feature group: ${GROUP_DIR}"
33+
34+
# Extract feature group name from directory
35+
GROUP_NAME=$(basename "${GROUP_DIR}")
36+
37+
# Tutorial file path
38+
TUTORIAL_FILE="${GROUP_DIR}/tutorial.md"
39+
40+
if [ -f "${TUTORIAL_FILE}" ]; then
41+
echo "Found tutorial for ${GROUP_NAME}"
42+
43+
# Use the folder name directly for the destination filename
44+
OUTPUT_FILENAME="${GROUP_NAME}.md"
45+
46+
# Copy the tutorial file
47+
cp "${TUTORIAL_FILE}" "${DOCS_TUTORIALS_DIR}/${OUTPUT_FILENAME}"
48+
echo "Copied ${TUTORIAL_FILE} to ${DOCS_TUTORIALS_DIR}/${OUTPUT_FILENAME}"
49+
else
50+
echo "Warning: No tutorial.md found for feature group ${GROUP_NAME}"
51+
fi
52+
done
53+
fi
54+
55+
# Copy the generated JSON file
56+
JSON_FILE="./_parsed/passport-features.json"
57+
if [ -f "${JSON_FILE}" ]; then
58+
# Create directory for JSON file if it doesn't exist
59+
JSON_DIR="${DOCS_REPO_DIR}/docs/main/example/zkEVM/unity/passport-examples"
60+
mkdir -p "${JSON_DIR}"
61+
62+
# Copy JSON file
63+
cp "${JSON_FILE}" "${JSON_DIR}/passport-features.json"
64+
echo "Copied ${JSON_FILE} to ${JSON_DIR}/passport-features.json"
65+
else
66+
echo "Warning: No passport-features.json found at ${JSON_FILE}"
67+
fi
68+
69+
echo "Passport tutorial processing complete."
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Publish Passport Tutorials
2+
3+
on:
4+
# Run when changes are pushed to Passport tutorials or metadata
5+
push:
6+
branches:
7+
# - main
8+
- chore/sample-app-tutorial
9+
paths:
10+
- 'sample/Assets/Scripts/Passport/features.json'
11+
- 'sample/Assets/Scripts/Passport/_tutorials/**/*'
12+
13+
# Allow manual triggering
14+
workflow_dispatch:
15+
16+
concurrency:
17+
group: passport-tutorials
18+
cancel-in-progress: false
19+
20+
jobs:
21+
PublishPassportTutorials:
22+
name: Process and Publish Passport Tutorials
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Checkout Unity SDK Repo
26+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
27+
with:
28+
fetch-depth: 0
29+
30+
- name: Create Parsed Directory
31+
run: mkdir -p _parsed
32+
33+
- name: Checkout Docs Repo
34+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
35+
with:
36+
repository: immutable/docs
37+
token: ${{ secrets.UNITY_SDK_DOCS_WORKFLOW }}
38+
path: imx-docs
39+
ref: 'main'
40+
41+
- name: Setup environment variables
42+
run: echo "CLONE_DIR=./imx-docs" >> $GITHUB_ENV
43+
44+
- name: Setup Git
45+
run: |
46+
git config --global user.name "${GITHUB_ACTOR}"
47+
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
48+
49+
- name: Install Dependencies
50+
run: |
51+
sudo apt-get update
52+
sudo apt-get install -y jq
53+
54+
- name: Process Passport Tutorials
55+
run: |
56+
# Make scripts executable
57+
chmod +x .github/scripts/aggregate-passport-metadata.js
58+
chmod +x .github/scripts/process-passport-tutorials.sh
59+
60+
# Generate aggregated JSON file
61+
node .github/scripts/aggregate-passport-metadata.js
62+
63+
# Process tutorials and copy to docs repo
64+
.github/scripts/process-passport-tutorials.sh
65+
shell: bash
66+
67+
- name: Commit and Push Changes to Docs Repo
68+
run: |
69+
cd "$CLONE_DIR"
70+
if git status --porcelain | grep -q .; then
71+
git add .
72+
73+
# Commit with reference to source commit
74+
COMMIT_MSG="docs: Update Passport tutorials from Unity SDK (Ref: ${GITHUB_SHA::8})"
75+
git commit -m "$COMMIT_MSG"
76+
77+
# Push to the target branch
78+
git push -u origin main
79+
echo "Successfully pushed Passport tutorial changes to docs repo"
80+
else
81+
echo "No changes to commit"
82+
fi
83+
shell: bash

0 commit comments

Comments
 (0)