The /scripts directory contains automation and helper scripts used for documentation, management of the API client npm package, etc.
Table of contents
- Scripts
Notes
- Python scripts require Python 3.x - it is meant to be used in pipeline workflows
- PowerShell scripts require PowerShell 5.1 or PowerShell Core 7+ - it is meant to be used on the developer’s machine
- Node.js scripts require Node.js 16+
- All scripts should be run from the project root directory
- GitHub Actions automatically set up required dependencies
Deployment Scripts
PowerShell-based deployment automation for Windows servers with persistent storage, atomic symlink swapping, and automatic rollback.
Overview
The deployment system provides a production-ready deployment solution for Windows servers:
- Persistent Storage - Symlinks preserve logs, cache, sessions across deployments
- Atomic Swaps - Safe production switchover with automatic rollback
- Comprehensive Validation - Pre-deployment checks for system prerequisites
- Easy Rollback - Previous deployments available for quick restoration
Required: Windows Server 2016+, PowerShell 5.0+, Administrator privileges, PHP 8.2+, MySQL/MariaDB
Scripts
| Script | Purpose |
|---|---|
Deploy-Application.ps1 |
Main deployment entry point |
InventoryApp.Deployment/InventoryApp.Deployment.psm1 |
Core deployment module with all functions |
InventoryApp.Deployment/InventoryApp.Deployment.psd1 |
Module manifest |
Quick Start
# Prepare database password
$dbPassword = ConvertTo-SecureString "password" -AsPlainText -Force
# Run deployment
.\scripts\Deploy-Application.ps1 `
-DeploymentPackagePath "C:\temp\inventory-app-release" `
-WebserverPath "C:\Apache24\htdocs\inventory-app" `
-SharedStorageRoot "C:\mwnf-server\github-apps" `
-PhpPath "C:\php\php.exe" `
-AppUrl "https://inventory.museumwnf.org" `
-AppName "Inventory App" `
-AppEnv "production" `
-AppKey "base64:xxxxx..." `
-DatabaseHost "127.0.0.1" `
-DatabasePort 3306 `
-DatabaseName "inventory_db" `
-DatabaseUsername "app" `
-DatabasePassword $dbPassword `
-Verbose
Deployment Phases
- Validation - System and package integrity
- Staging Preparation - Create timestamped directory
- Persistent Storage - Setup symlinks
- Application Down - Maintenance mode
- Production Swap - Atomic symlink switch
- Configuration - Generate
.env - Laravel Setup - Migrations and caching
- Cleanup - Remove old deployments
Directory Structure
C:\mwnf-server\github-apps\
├─ production/ (symlink → staging-YYYYMMDD-HHMMSS)
├─ staging-20251031-041516/ (current active)
│ └─ storage/ (symlink → ../shared-storage/storage)
├─ staging-20251030-123456/ (previous - for rollback)
└─ shared-storage/storage/ (persistent data)
├─ logs/ (preserved across deployments)
├─ framework/cache/
├─ framework/sessions/
└─ framework/views/
Rollback
Automatic: If deployment fails after production swap, previous version is automatically restored.
Manual:
# List available versions
Get-ChildItem -Path "C:\mwnf-server\github-apps" -Directory -Filter "staging-*" |
Sort-Object -Property Name -Descending
# Restore specific version
Remove-Item "C:\Apache24\htdocs\inventory-app" -Force
New-Item -ItemType Junction `
-Path "C:\Apache24\htdocs\inventory-app" `
-Target "C:\mwnf-server\github-apps\staging-PREVIOUS-VERSION"
References
| Reference | Url |
|---|---|
| Deployment Guide | https://metanull.github.io/inventory-app/deployment/ |
| Release Artifacts | https://github.com/metanull/inventory-app/releases |
| GitHub Actions Workflow | /.github/workflows/release-deployment.yml |
Scripts used in CI/CD Workflows
Auto-generation of the static documentation website
These scripts are triggered by the CI/CD Workflow action .github/workflows/continuous-deployment_github-pages.yml responsible for deploying the static documentation website to github.io.
See:
- /.github/workflows/README.md for workflow details
- /docs/README.md for Jekyll site documentation
Generating the Git Commit History
Converts Git commit history into Jekyll-compatible markdown pages.
These files are integrated by Jekyll into the static documentation website under /inventory-app/development/archive.
The script is called by CI workflows on push to main.
See:
- /.github/workflows/README.md for workflow details
- /docs/README.md for Jekyll integration
Script properties
| Property | Value |
|---|---|
| Script | generate-commit-docs.py |
| Invoker | Invoked by .github/workflows/continuous-deployment_github-pages.yml on push to main. See /.github/workflows/README.md |
| Input | It reads from git directly |
| Output | /docs/_docs/**/*.md |
| Log | /docs/commit-docs.log |
Links
| Reference | Url |
|---|---|
| Git Commit History | https://metanull.github.io/inventory-app/development/archive |
Usage:
# Run from project root
python scripts/generate-commit-docs.py
Generating the API client npm package’s static documentation
Transforms the TypeScript API Client markdown files (auto-generated) into Jekyll-compatible markdown pages; fixes the relative hyperlinks they contain; and generates an Index markdown file.
These files are integrated by Jekyll into the static documentation website under /inventory-app/api-client/.
The script is called by CI workflows on push to main.
See:
- /.github/workflows/README.md for workflow details
- /docs/README.md for Jekyll integration
Script properties
| Property | Value |
|---|---|
| Script | generate-client-docs.py |
| Invoker | Invoked by .github/workflows/continuous-deployment_github-pages.yml on push to main. See /.github/workflows/README.md |
| Input | /api-client/docs/*.md - These files are auto-generated during development and not directly suitable for integration by Jekyll. See Generating the API client npm package |
| Output | /docs/api-client/*.md |
| Log | /docs/client-docs.log |
Links
| Reference | Url |
|---|---|
| Static documentation of the API client npm package | https://metanull.github.io/inventory-app/api-client/ |
Usage:
# Requires TypeScript client to be generated first
# See: (Generating the API client npm package)
# Then generate documentation
python scripts/generate-client-docs.py
Scripts used locally during development
Auto-generation of the API client npm package
Authenticating with GitHub Packages
Configures authentication with GitHub Packages by creating or updating the .npmrc file. It is required to install the API client npm package from the GitHub Packages npm repository.
Script properties
| Property | Value |
|---|---|
| Script | Setup-GithubPackages.ps1 |
| Invoker | Invoked by the developer once, or after changing their Personal Access Token |
| Input | The script prompts information from the user |
| Output | /.npmrc |
| Log | N/A - The script writes to the terminal |
Usage
. ./scripts/Setup-GithubPackages.ps1
Generating the API client npm package
Reads the specifications of the API exposed by the Laravel project, and generates:
- an OpenApi documentation -
/docs/_openapi/api.json - an API client npm package -
/api-client/*. - static documentation of the npm package -
/api-client/docs/*.md
Script properties
| Property | Value |
|---|---|
| Script | generate-api-client.ps1 |
| Invoker | Invoked by the developer after change to the api |
| Input 1 | /app - The source code of the Laravel application |
| Input 2 | /scripts/api-client-config.psd1 - Configuration of API client generation scripts |
| Output 1 | /docs/_openapi/api.json |
| Output 2 | /api-client/package.json, /api-client/*.ts |
| Output 3 | /api-client/docs/*.md |
| Log | N/A - The script writes to the terminal |
Links
| Reference | Url |
|---|---|
| Documentation | https://metanull.github.io/inventory-app/api/ |
| API’s OpenAPI specification (api.json) | https://metanull.github.io/inventory-app/api.json |
| Swagger UI for the API’s OpenAPI specification | https://metanull.github.io/inventory-app/swagger-ui.html |
| API client npm package | https://github.com/metanull?tab=packages&repo_name=inventory-app |
| Static documentation of the API client npm package | https://metanull.github.io/inventory-app/api-client/ |
Usage
IMPORTANT: DO use the composer command composer ci-openapi-doc, as it first generates up to date api.json then calls generate-api-client.ps1
composer ci-openapi-doc
Alternatively, use:
# Update the OpenAPI specification (/docs/_openapi/api.json)
# php artisan scramble:export --path=docs/_openapi/api.json --ansi
# Generate the API client npm package
#. ./scripts/generate-api-client.ps1
Publishing the API client npm package to the GitHub Packages npm registry
Publishes the API client npm package to the GitHub Packages npm registry
Script properties
| Property | Value |
|---|---|
| Script | publish-api-client.ps1 |
| Invoker | Invoked by the developer after Generating the API client npm package |
| Input 1 | /api-client/package.json, /api-client/*.ts. See Generating the API client npm package |
| Input 2 | User’s GitHub personal access token, with adequate permissions |
| Output | https://github.com/metanull/inventory-app/pkgs/npm/inventory-app-api-client |
| Log | N/A - The script writes to the terminal |
Links
| Reference | Url |
|---|---|
| GitHub Packages | https://docs.github.com/en/packages |
| @metanull/inventory-app-api-client | https://github.com/metanull/inventory-app/pkgs/npm/inventory-app-api-client |
| GitHub Packages in inventory-app | https://github.com/metanull?tab=packages&repo_name=inventory-app |
Usage
# Requires API client npm package to be generated
# Requires GitHub Personal Access Token
. ./scripts/publish-api-client.ps1 -Credential (Get-Credential)
Generation of the static documentation website
Generating the static documentation website locally
Invokes the Jekyll Ruby Gem in a Windows Subsystem for Linux (WSL) terminal; it transforms the content of /docs into a static website.
See /docs/README.md for Jekyll site documentation.
Script properties
| Property | Value |
|---|---|
| Script | jekyll-build.ps1 |
| Invoker | Invoked by the developer after change to /docs/**/*.md |
| Input | /docs |
| Output | /docs/_site/** |
| Log | N/A - The script writes to the terminal |
Usage
# Build with defaults
. ./scripts/jekyll-build.ps1
# Build with custom base URL
. ./scripts/jekyll-build.ps1 -BaseUrl "/my-app"
# Clean build
. ./scripts/jekyll-build.ps1 -Clean
Requirements
- WSL (Windows Subsystem for Linux) installed
- Ruby installed in WSL (user-installed required)
- Jekyll and bundler gems installed
Running the static documentation website locally
Serves the static documentation website on a local URL http://localhost:4000.
See /docs/README.md for Jekyll site documentation.
Script properties
| Property | Value |
|---|---|
| Script | jekyll-serve.ps1 |
| Invoker | Invoked by the developer after change to /docs/**/*.md |
| Input | /docs |
| Output 1 | /docs/_site/** |
| Output 2 | http://localhost:4000 |
| Log | N/A - The script writes to the terminal |
Links
| Reference | Url |
|---|---|
| Local static documentation website | http://localhost:4000 |
Usage
# Serve with defaults (http://127.0.0.1:4000)
. ./scripts/jekyll-serve.ps1
# Custom port
. ./scripts/jekyll-serve.ps1 -Port 8080
# Enable LiveReload
. ./scripts/jekyll-serve.ps1 -LiveReload
# Serve on all network interfaces
. ./scripts/jekyll-serve.ps1 -Host 0.0.0.0
Requirements
- WSL (Windows Subsystem for Linux) installed
- Ruby installed in WSL (user-installed required)
- Jekyll and bundler gems installed
Auto-generating the Model documentation
Auto-generates markdown documentation for Laravel models (schemas, relations, fields).
Script properties
| Property | Value |
|---|---|
| Script | generate-model-documentation.ps1 |
| Invoker | Invoked by the developer after change to the models |
| Input | /app |
| Output | /docs/_model/** |
| Log | N/A - The script writes to the terminal |
Usage
# Generate/update model documentation
. ./scripts/generate-model-documentation.ps1
# Force regenerate all documentation
. ./scripts/generate-model-documentation.ps1 -Force
Local CI/CD Build Simulation
Simulates the GitHub continuous deployment build pipeline locally, allowing validation that changes will build successfully before pushing to GitHub.
Script properties
| Property | Value |
|---|---|
| Script | Invoke-LocalCDBuild.ps1 |
| Invoker | Invoked by the developer after code changes to validate the build |
| Input | Git repository, branch name, .npmrc file (all auto-detected) |
| Output | N/A - Temp directory is cleaned up automatically |
| Log | N/A - The script writes to the terminal |
Usage
All parameters are auto-detected from your current working directory if not provided:
# Run with all parameters auto-detected from current git repo
./scripts/Invoke-LocalCDBuild.ps1
# Or specify parameters explicitly
./scripts/Invoke-LocalCDBuild.ps1 `
-RepositoryUrl "https://github.com/metanull/inventory-app.git" `
-BranchName "main" `
-NpmrcPath "$HOME\.npmrc"
Parameters
- RepositoryUrl (optional): Git repository URL. Auto-detected from
git remote originif not provided. - BranchName (optional): Branch name to checkout. Auto-detected from current branch if not provided.
- NpmrcPath (optional): Path to
.npmrcfile. Defaults to$HOME\.npmrcif not provided.
What it does
- Checks for uncommitted or staged changes (fails if any exist)
- Verifies
.npmrcfile exists - Clones repository to temp directory
- Checks out the specified branch
- Installs PHP and NPM dependencies (production flags)
- Builds backend assets
- Builds SPA assets
- Cleans up temporary files
Exit codes
- 0: Success
- 1: Failure (see error message)
Development helpers
Image seeding
Downloads and stores a set of images from the internet to avoid repeating this time consuming when seeding the database.
Script properties
| Property | Value |
|---|---|
| Script | download-seed-images.ps1 |
| Invoker | Invoked by the developer once |
| Input | https://picsum.photos |
| Output | /database/seeders/data/images |
| Log | N/A - The script writes to the terminal |
Links
| Reference | Url |
|---|---|
| Lorem Picsum, The Lorem Ipsum for photos. | https://picsum.photos |
Usage
. ./scripts/download-seed-images.ps1
Migration testing
Runs database migration back and forth a small number of times to help detect issues. It uses an array of environment files to run the tests in multiple environments.
Script properties
| Property | Value |
|---|---|
| Script | test-migrations.ps1 |
| Invoker | Invoked by the developer after a change to the migrations |
| Input | /database/migrations |
| Output | N/A - The script writes to the terminal |
| Log | N/A - The script writes to the terminal |
Usage
. ./scripts/test-migrations.ps1
Validation of the Workflow files
Validates all YAML workflow files.
Script properties
| Property | Value |
|---|---|
| Script | validate-workflows.cjs |
| Invoker | Invoked by the developer after a change to workflow’s *.yml files using node ./scripts/validate-workflows.cjs. See /.github/workflows/README.md |
| Input | /.github/workflows |
| Output | N/A - The script writes to the terminal |
| Log | N/A - The script writes to the terminal |
Links
| Reference | Url |
|---|---|
| npx, Run a command from a local or remote npm package | https://docs.npmjs.com/cli/v9/commands/npx?v=true |
Usage
node scripts/validate-workflows.cjs
Running tests in parallel
Run all tests suites in parallel.
Script properties
| Property | Value |
|---|---|
| Script | Start-Tests.ps1 |
| Invoker | Invoked by the developer to efficiently run all tests after a change to the code |
| Input | /tests, /resource/js/**/tests */ |
| Output | N/A - The script writes to the terminal |
| Log | N/A - The script writes to the terminal |
Usage
.\Scripts\Start-Tests.ps1