Skip to content

chore: sample app tutorial automation #474

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5dbcbf2
chore: rename PassportInit script file name
darrenmelvison1 May 19, 2025
fc11373
Merge branch 'chore/sample-app-refactor' into chore/sample-app-tutorial
darrenmelvison1 May 19, 2025
46e96e8
feat: generated tutorial walkthroughs for all passport features
darrenmelvison1 May 19, 2025
63dada5
feat: pipeline to push the sample app's tutorials to the docs site
darrenmelvison1 May 19, 2025
6323bd2
fix: updated tutorial workflow
darrenmelvison1 May 19, 2025
dc3cb9b
chore: testing new workflow
darrenmelvison1 May 19, 2025
7014928
fix: updated scripts to ensure it produces the correct JSON format ou…
darrenmelvison1 May 20, 2025
37e4506
chore: merging fixed unity scenes
darrenmelvison1 May 20, 2025
940de10
Merge branch 'main' into chore/sample-app-tutorial
darrenmelvison1 May 21, 2025
24ca072
fix: handle null delimited filenames
darrenmelvison1 May 21, 2025
46f524c
fix: linting issues
darrenmelvison1 May 22, 2025
361497f
chore: changed workflow secret
darrenmelvison1 May 22, 2025
87e1071
fix: changed directory and target branch for more testing
darrenmelvison1 May 22, 2025
32bfc3e
test: workflow test on new docs dir structure
darrenmelvison1 May 22, 2025
d194322
chore: revamped tutorial structure to be under feature groups
darrenmelvison1 May 22, 2025
ba1e404
test: new feature grouping test
darrenmelvison1 May 22, 2025
78d78bc
test: updated workflow testing
darrenmelvison1 May 22, 2025
1d88974
chore: remove kebab case conversion in workflow script
darrenmelvison1 May 22, 2025
46feebe
test: another workflow trial on the docs
darrenmelvison1 May 22, 2025
390141d
Merge branch 'main' into chore/sample-app-tutorial
darrenmelvison1 May 22, 2025
2651f5a
test: replicate workflow to main to test
darrenmelvison1 May 22, 2025
797e2a5
chore: changed docs repo target branch to main
darrenmelvison1 May 22, 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
148 changes: 148 additions & 0 deletions .github/scripts/aggregate-passport-metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env node

'use strict';

const fs = require('fs');
const path = require('path');

// Configuration
const PASSPORT_ROOT = './sample/Assets/Scripts/Passport';
const TUTORIALS_DIR = path.join(PASSPORT_ROOT, '_tutorials');
const OUTPUT_DIR = './_parsed';
const OUTPUT_FILE = path.join(OUTPUT_DIR, 'passport-features.json');
const FEATURES_JSON_PATH = path.join(PASSPORT_ROOT, 'features.json');

// Ensure output directory exists
try {
if (!fs.existsSync(OUTPUT_DIR)) {
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
}
} catch (error) {
console.error(`Error creating output directory: ${error.message}`);
process.exit(1);
}

console.log('Processing Passport features metadata...');

// Load features.json to get feature groups and their features
let featureGroups = {};
try {
const featuresContent = fs.readFileSync(FEATURES_JSON_PATH, 'utf8');
const featuresJson = JSON.parse(featuresContent);
featureGroups = featuresJson.features || {};
} catch (error) {
console.error(`Error reading features.json: ${error.message}`);
process.exit(1);
}

// Find all feature group directories in _tutorials
const findFeatureGroupDirectories = () => {
const featureGroupDirs = [];

if (!fs.existsSync(TUTORIALS_DIR)) {
console.warn(`Tutorials directory does not exist: ${TUTORIALS_DIR}`);
return featureGroupDirs;
}

try {
const dirs = fs.readdirSync(TUTORIALS_DIR, { withFileTypes: true });

dirs.forEach((dirent) => {
if (dirent.isDirectory()) {
featureGroupDirs.push(path.join(TUTORIALS_DIR, dirent.name));
}
});
} catch (err) {
console.warn(`Error reading tutorials directory ${TUTORIALS_DIR}: ${err.message}`);
}

return featureGroupDirs;
};

// Process metadata files
const processFeatureGroups = (featureGroupDirs) => {
const featuresObject = {};

featureGroupDirs.forEach((groupDir) => {
const groupName = path.basename(groupDir);
console.log(`Processing feature group: ${groupName}`);

// Check if this group exists in features.json (case-insensitive)
const matchingGroup = Object.keys(featureGroups).find(
key => key.toLowerCase() === groupName.toLowerCase()
);

if (!matchingGroup) {
console.warn(`Feature group ${groupName} not found in features.json, skipping`);
return;
}

// Path to metadata.json in this feature group directory
const metadataPath = path.join(groupDir, 'metadata.json');
if (!fs.existsSync(metadataPath)) {
console.warn(`No metadata.json found for feature group ${groupName} in ${groupDir}`);
return;
}

// Path to tutorial.md in this feature group directory
const tutorialPath = path.join(groupDir, 'tutorial.md');
const tutorialExists = fs.existsSync(tutorialPath);

// Use the folder name directly as the feature key
const featureKey = groupName;

if (!featureKey) {
console.warn(`Generated empty feature key for ${groupDir}, skipping`);
return;
}

const tutorialFile = tutorialExists ? `${featureKey}.md` : null;

if (!tutorialExists) {
console.warn(`No tutorial.md found for feature group ${groupName} in ${groupDir}`);
}

// Read and process metadata
try {
const metadataContent = fs.readFileSync(metadataPath, 'utf8');
const metadata = JSON.parse(metadataContent);

// Add additional fields
metadata.title = metadata.title || matchingGroup;
metadata.sidebar_order = metadata.sidebar_order || 0;
metadata.deprecated = metadata.deprecated || false;

// Add feature group information
metadata.feature_group = matchingGroup;
metadata.features = Object.keys(featureGroups[matchingGroup] || {});

// Create the feature entry
featuresObject[featureKey] = {
tutorial: tutorialFile,
metadata: metadata
};
} catch (error) {
console.error(`Error processing metadata file ${metadataPath}: ${error.message}`);
}
});

return featuresObject;
};

try {
// Main execution
const featureGroupDirs = findFeatureGroupDirectories();

if (featureGroupDirs.length === 0) {
console.warn('No feature group directories found. Output file will be empty.');
}

const features = processFeatureGroups(featureGroupDirs);

// Create the final passport-features.json
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(features, null, 2));
console.log(`Created ${OUTPUT_FILE}`);
} catch (error) {
console.error(`Fatal error: ${error.message}`);
process.exit(1);
}
69 changes: 69 additions & 0 deletions .github/scripts/process-passport-tutorials.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash

set -e
set -x

# Directory where docs repo is cloned
DOCS_REPO_DIR="${CLONE_DIR:-"./imx-docs"}"

# Root of the Passport features
PASSPORT_ROOT="./sample/Assets/Scripts/Passport"
TUTORIALS_DIR="${PASSPORT_ROOT}/_tutorials"

echo "Processing Passport tutorials..."

# Load features.json to get feature groups
FEATURES_JSON="${PASSPORT_ROOT}/features.json"
if [ ! -f "${FEATURES_JSON}" ]; then
echo "Error: features.json not found at ${FEATURES_JSON}"
exit 1
fi

# Create _tutorials directory in docs repo
DOCS_TUTORIALS_DIR="${DOCS_REPO_DIR}/docs/main/example/zkEVM/unity/passport-examples/_tutorials"
mkdir -p "${DOCS_TUTORIALS_DIR}"

# Check if _tutorials directory exists
if [ ! -d "${TUTORIALS_DIR}" ]; then
echo "Warning: _tutorials directory not found at ${TUTORIALS_DIR}"
else
# Process each feature group directory in _tutorials
find "${TUTORIALS_DIR}" -mindepth 1 -maxdepth 1 -type d -print0 | while IFS= read -r -d '' GROUP_DIR; do
echo "Processing feature group: ${GROUP_DIR}"

# Extract feature group name from directory
GROUP_NAME=$(basename "${GROUP_DIR}")

# Tutorial file path
TUTORIAL_FILE="${GROUP_DIR}/tutorial.md"

if [ -f "${TUTORIAL_FILE}" ]; then
echo "Found tutorial for ${GROUP_NAME}"

# Use the folder name directly for the destination filename
OUTPUT_FILENAME="${GROUP_NAME}.md"

# Copy the tutorial file
cp "${TUTORIAL_FILE}" "${DOCS_TUTORIALS_DIR}/${OUTPUT_FILENAME}"
echo "Copied ${TUTORIAL_FILE} to ${DOCS_TUTORIALS_DIR}/${OUTPUT_FILENAME}"
else
echo "Warning: No tutorial.md found for feature group ${GROUP_NAME}"
fi
done
fi

# Copy the generated JSON file
JSON_FILE="./_parsed/passport-features.json"
if [ -f "${JSON_FILE}" ]; then
# Create directory for JSON file if it doesn't exist
JSON_DIR="${DOCS_REPO_DIR}/docs/main/example/zkEVM/unity/passport-examples"
mkdir -p "${JSON_DIR}"

# Copy JSON file
cp "${JSON_FILE}" "${JSON_DIR}/passport-features.json"
echo "Copied ${JSON_FILE} to ${JSON_DIR}/passport-features.json"
else
echo "Warning: No passport-features.json found at ${JSON_FILE}"
fi

echo "Passport tutorial processing complete."
83 changes: 83 additions & 0 deletions .github/workflows/publish-passport-tutorials.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Publish Passport Tutorials

on:
# Run when changes are pushed to Passport tutorials or metadata
push:
branches:
# - main
- chore/sample-app-tutorial
paths:
- 'sample/Assets/Scripts/Passport/features.json'
- 'sample/Assets/Scripts/Passport/_tutorials/**/*'

# Allow manual triggering
workflow_dispatch:

concurrency:
group: passport-tutorials
cancel-in-progress: false

jobs:
PublishPassportTutorials:
name: Process and Publish Passport Tutorials
runs-on: ubuntu-latest
steps:
- name: Checkout Unity SDK Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
fetch-depth: 0

- name: Create Parsed Directory
run: mkdir -p _parsed

- name: Checkout Docs Repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
with:
repository: immutable/docs
token: ${{ secrets.UNITY_SDK_DOCS_WORKFLOW }}
path: imx-docs
ref: 'main'

- name: Setup environment variables
run: echo "CLONE_DIR=./imx-docs" >> $GITHUB_ENV

- name: Setup Git
run: |
git config --global user.name "${GITHUB_ACTOR}"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"

- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y jq

- name: Process Passport Tutorials
run: |
# Make scripts executable
chmod +x .github/scripts/aggregate-passport-metadata.js
chmod +x .github/scripts/process-passport-tutorials.sh

# Generate aggregated JSON file
node .github/scripts/aggregate-passport-metadata.js

# Process tutorials and copy to docs repo
.github/scripts/process-passport-tutorials.sh
shell: bash

- name: Commit and Push Changes to Docs Repo
run: |
cd "$CLONE_DIR"
if git status --porcelain | grep -q .; then
git add .

# Commit with reference to source commit
COMMIT_MSG="docs: Update Passport tutorials from Unity SDK (Ref: ${GITHUB_SHA::8})"
git commit -m "$COMMIT_MSG"

# Push to the target branch
git push -u origin main
echo "Successfully pushed Passport tutorial changes to docs repo"
else
echo "No changes to commit"
fi
shell: bash
Loading
Loading