Merge pull request 'chore: initial workflow implementation' (#1) from chore/initial-implementation into main
Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
411
.github/workflows/test.yml
vendored
Normal file
411
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
name: Test Module Installation Action
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Test basic single module installation
|
||||||
|
test-single-module:
|
||||||
|
name: Single Module (No Dependencies)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout action-module-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
path: action-module-install
|
||||||
|
|
||||||
|
- name: Checkout action-server-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
repository: Nodarx/action-server-install
|
||||||
|
ref: main
|
||||||
|
path: action-server-install
|
||||||
|
github-server-url: https://git.ktrix.dev
|
||||||
|
|
||||||
|
- name: Setup server environment
|
||||||
|
uses: ./action-server-install
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
node-version: '24'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
- name: Create test module repository
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/test-repos/simple-module
|
||||||
|
cd /tmp/test-repos/simple-module
|
||||||
|
git init
|
||||||
|
git config user.email "test@example.com"
|
||||||
|
git config user.name "Test User"
|
||||||
|
|
||||||
|
# Create a simple Node.js module
|
||||||
|
cat > package.json << 'EOF'
|
||||||
|
{
|
||||||
|
"name": "simple-module",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Test module",
|
||||||
|
"main": "index.js"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "console.log('Simple module loaded');" > index.js
|
||||||
|
|
||||||
|
git add .
|
||||||
|
git commit -m "Initial commit"
|
||||||
|
|
||||||
|
- name: Install single module
|
||||||
|
id: install
|
||||||
|
uses: ./action-module-install
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "simple-module",
|
||||||
|
"repo": "file:///tmp/test-repos/simple-module"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: Verify installation
|
||||||
|
run: |
|
||||||
|
echo "Checking installation..."
|
||||||
|
|
||||||
|
# Check module directory exists
|
||||||
|
if [ ! -d "./modules/simple-module" ]; then
|
||||||
|
echo "::error::Module directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check files were cloned
|
||||||
|
if [ ! -f "./modules/simple-module/package.json" ]; then
|
||||||
|
echo "::error::package.json not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check npm install result (node_modules required only if production deps exist)
|
||||||
|
DEP_COUNT=$(node -e 'const p=require("./modules/simple-module/package.json"); const c=Object.keys(p.dependencies||{}).length+Object.keys(p.optionalDependencies||{}).length; console.log(c);')
|
||||||
|
if [ "$DEP_COUNT" -gt 0 ] && [ ! -d "./modules/simple-module/node_modules" ]; then
|
||||||
|
echo "::error::node_modules not found for module with production dependencies"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check outputs
|
||||||
|
if [ "${{ steps.install.outputs.status }}" != "success" ]; then
|
||||||
|
echo "::error::Installation status is not success"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${{ steps.install.outputs.installed-modules }}" != "simple-module" ]; then
|
||||||
|
echo "::error::Installed modules output is incorrect"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Single module installation verified"
|
||||||
|
|
||||||
|
# Test PHP module
|
||||||
|
test-php-module:
|
||||||
|
name: PHP Module with Composer
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout action-module-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
path: action-module-install
|
||||||
|
|
||||||
|
- name: Checkout action-server-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
repository: Nodarx/action-server-install
|
||||||
|
ref: main
|
||||||
|
path: action-server-install
|
||||||
|
github-server-url: https://git.ktrix.dev
|
||||||
|
|
||||||
|
- name: Setup PHP environment
|
||||||
|
uses: ./action-server-install
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
- name: Create PHP test module
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/test-repos/php-module
|
||||||
|
cd /tmp/test-repos/php-module
|
||||||
|
git init
|
||||||
|
git config user.email "test@example.com"
|
||||||
|
git config user.name "Test User"
|
||||||
|
|
||||||
|
cat > composer.json << 'EOF'
|
||||||
|
{
|
||||||
|
"name": "test/php-module",
|
||||||
|
"description": "PHP test module",
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Test\\PhpModule\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir -p src
|
||||||
|
cat > src/TestClass.php << 'EOF'
|
||||||
|
<?php
|
||||||
|
namespace Test\PhpModule;
|
||||||
|
|
||||||
|
class TestClass {
|
||||||
|
public function getMessage() {
|
||||||
|
return "PHP Module loaded";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git add . && git commit -m "Initial commit"
|
||||||
|
|
||||||
|
- name: Install PHP module
|
||||||
|
uses: ./action-module-install
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "php-module",
|
||||||
|
"repo": "file:///tmp/test-repos/php-module"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: Verify PHP installation
|
||||||
|
run: |
|
||||||
|
# Check composer.json exists
|
||||||
|
if [ ! -f "./modules/php-module/composer.json" ]; then
|
||||||
|
echo "::error::composer.json not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check vendor directory created
|
||||||
|
if [ ! -d "./modules/php-module/vendor" ]; then
|
||||||
|
echo "::error::vendor directory not found - composer install failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check autoload file exists
|
||||||
|
if [ ! -f "./modules/php-module/vendor/autoload.php" ]; then
|
||||||
|
echo "::error::autoload.php not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ PHP module installation verified"
|
||||||
|
|
||||||
|
# Test Node.js module
|
||||||
|
test-node-module:
|
||||||
|
name: Node.js Module with NPM
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout action-module-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
path: action-module-install
|
||||||
|
|
||||||
|
- name: Checkout action-server-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
repository: Nodarx/action-server-install
|
||||||
|
ref: main
|
||||||
|
path: action-server-install
|
||||||
|
github-server-url: https://git.ktrix.dev
|
||||||
|
|
||||||
|
- name: Setup Node.js environment
|
||||||
|
uses: ./action-server-install
|
||||||
|
with:
|
||||||
|
install-node: 'true'
|
||||||
|
node-version: '24'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
- name: Create Node.js test module
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/test-repos/vue-module
|
||||||
|
cd /tmp/test-repos/vue-module
|
||||||
|
git init
|
||||||
|
git config user.email "test@example.com"
|
||||||
|
git config user.name "Test User"
|
||||||
|
|
||||||
|
cat > package.json << 'EOF'
|
||||||
|
{
|
||||||
|
"name": "vue-module",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Vue test module",
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > index.js << 'EOF'
|
||||||
|
export default {
|
||||||
|
name: 'VueModule',
|
||||||
|
getMessage() {
|
||||||
|
return 'Vue module loaded';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EOF
|
||||||
|
|
||||||
|
git add . && git commit -m "Initial commit"
|
||||||
|
|
||||||
|
- name: Install Node.js module
|
||||||
|
uses: ./action-module-install
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "vue-module",
|
||||||
|
"repo": "file:///tmp/test-repos/vue-module"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: Verify Node.js installation
|
||||||
|
run: |
|
||||||
|
# Check package.json exists
|
||||||
|
if [ ! -f "./modules/vue-module/package.json" ]; then
|
||||||
|
echo "::error::package.json not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check npm install result (node_modules required only if production deps exist)
|
||||||
|
DEP_COUNT=$(node -e 'const p=require("./modules/vue-module/package.json"); const c=Object.keys(p.dependencies||{}).length+Object.keys(p.optionalDependencies||{}).length; console.log(c);')
|
||||||
|
if [ "$DEP_COUNT" -gt 0 ] && [ ! -d "./modules/vue-module/node_modules" ]; then
|
||||||
|
echo "::error::node_modules directory not found for module with production dependencies"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Node.js module installation verified"
|
||||||
|
|
||||||
|
# Test mixed PHP and Node.js modules
|
||||||
|
test-mixed-modules:
|
||||||
|
name: Mixed PHP and Node Modules
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout action-module-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
path: action-module-install
|
||||||
|
|
||||||
|
- name: Checkout action-server-install
|
||||||
|
uses: actions/checkout@v6.0.2
|
||||||
|
with:
|
||||||
|
repository: Nodarx/action-server-install
|
||||||
|
ref: main
|
||||||
|
path: action-server-install
|
||||||
|
github-server-url: https://git.ktrix.dev
|
||||||
|
|
||||||
|
- name: Setup both PHP and Node.js
|
||||||
|
uses: ./action-server-install
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
node-version: '24'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
- name: Create mixed test modules
|
||||||
|
run: |
|
||||||
|
# PHP backend module
|
||||||
|
mkdir -p /tmp/test-repos/backend
|
||||||
|
cd /tmp/test-repos/backend
|
||||||
|
git init
|
||||||
|
git config user.email "test@example.com"
|
||||||
|
git config user.name "Test User"
|
||||||
|
cat > composer.json << 'EOF'
|
||||||
|
{
|
||||||
|
"name": "test/backend",
|
||||||
|
"require": {}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git add . && git commit -m "Initial commit"
|
||||||
|
|
||||||
|
# Node.js frontend module
|
||||||
|
mkdir -p /tmp/test-repos/frontend
|
||||||
|
cd /tmp/test-repos/frontend
|
||||||
|
git init
|
||||||
|
git config user.email "test@example.com"
|
||||||
|
git config user.name "Test User"
|
||||||
|
cat > package.json << 'EOF'
|
||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
git add . && git commit -m "Initial commit"
|
||||||
|
|
||||||
|
- name: Install mixed modules
|
||||||
|
uses: ./action-module-install
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "backend",
|
||||||
|
"repo": "file:///tmp/test-repos/backend"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"repo": "file:///tmp/test-repos/frontend"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: Verify mixed installation
|
||||||
|
run: |
|
||||||
|
# Verify PHP module
|
||||||
|
if [ ! -d "./modules/backend/vendor" ]; then
|
||||||
|
echo "::error::Backend composer dependencies not installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify Node module (node_modules required only if production deps exist)
|
||||||
|
DEP_COUNT=$(node -e 'const p=require("./modules/frontend/package.json"); const c=Object.keys(p.dependencies||{}).length+Object.keys(p.optionalDependencies||{}).length; console.log(c);')
|
||||||
|
if [ "$DEP_COUNT" -gt 0 ] && [ ! -d "./modules/frontend/node_modules" ]; then
|
||||||
|
echo "::error::Frontend module has production dependencies but node_modules is missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Mixed PHP and Node.js modules verified"
|
||||||
|
|
||||||
|
# Test summary
|
||||||
|
test-summary:
|
||||||
|
name: Test Summary
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- test-single-module
|
||||||
|
- test-php-module
|
||||||
|
- test-node-module
|
||||||
|
- test-mixed-modules
|
||||||
|
if: always()
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check test results
|
||||||
|
run: |
|
||||||
|
echo "## Test Results Summary" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Test | Result |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Single Module | ${{ needs.test-single-module.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| PHP Module | ${{ needs.test-php-module.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Node Module | ${{ needs.test-node-module.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "| Mixed Modules | ${{ needs.test-mixed-modules.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
# Check if any test failed
|
||||||
|
if [ "${{ needs.test-single-module.result }}" != "success" ] || \
|
||||||
|
[ "${{ needs.test-php-module.result }}" != "success" ] || \
|
||||||
|
[ "${{ needs.test-node-module.result }}" != "success" ] || \
|
||||||
|
[ "${{ needs.test-mixed-modules.result }}" != "success" ]; then
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "❌ One or more tests failed" >> $GITHUB_STEP_SUMMARY
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "✅ All tests passed!" >> $GITHUB_STEP_SUMMARY
|
||||||
407
README.md
407
README.md
@@ -1,2 +1,407 @@
|
|||||||
# action-module-install
|
# Nodarx Module Install Action
|
||||||
|
|
||||||
|
Install custom PHP/Vue modules from git repositories with automatic dependency resolution.
|
||||||
|
|
||||||
|
This GitHub Action clones module repositories, resolves dependencies, and installs both PHP (Composer) and Node.js (npm) dependencies in the correct order.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- 🔗 **Dependency Resolution**: Automatically orders modules based on their dependencies
|
||||||
|
- 📦 **Multi-Language Support**: Handles both PHP (Composer) and Node.js (npm) projects
|
||||||
|
- 🔄 **Flexible**: Support for custom branches, tags, or commits
|
||||||
|
- ✅ **Validation**: Detects circular dependencies and validates module configuration
|
||||||
|
- 🎯 **Simple**: Just provide a JSON array of modules and their dependencies
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Deploy with Modules
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Install server environment (PHP + Node.js)
|
||||||
|
- uses: Nodarx/action-server-install@v1
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
node-version: '24'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
# Install modules with dependencies
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "mail_manager", "repo": "https://git.ktrix.dev/Nodarx/mail_manager"},
|
||||||
|
{"name": "provider_jmapc", "repo": "https://git.ktrix.dev/Nodarx/provider_jmapc"},
|
||||||
|
{"name": "mail", "repo": "https://git.ktrix.dev/Nodarx/mail", "dependencies": ["mail_manager", "provider_jmapc"]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Inputs
|
||||||
|
|
||||||
|
| Input | Description | Required | Default |
|
||||||
|
|-------|-------------|----------|---------|
|
||||||
|
| `modules` | JSON array of modules to install (see [Module Schema](#module-schema)) | Yes | - |
|
||||||
|
| `install-path` | Base directory where modules will be installed | No | `./modules` |
|
||||||
|
| `skip-dependencies-check` | Skip dependency validation (not recommended) | No | `false` |
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
|
||||||
|
| Output | Description | Example |
|
||||||
|
|--------|-------------|---------|
|
||||||
|
| `installed-modules` | Comma-separated list of installed module names in installation order | `mail_manager,provider_jmapc,mail` |
|
||||||
|
| `install-path` | Path where modules were installed | `./modules` |
|
||||||
|
| `status` | Installation status | `success` |
|
||||||
|
|
||||||
|
## Module Schema
|
||||||
|
|
||||||
|
Each module in the `modules` array should follow this structure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "module-name", // Required: Unique module identifier
|
||||||
|
"repo": "https://...", // Required: Git repository URL
|
||||||
|
"branch": "main", // Optional: Branch, tag, or commit (default: main)
|
||||||
|
"dependencies": ["module1"] // Optional: Array of module names this module depends on
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Module Schema Examples
|
||||||
|
|
||||||
|
**Minimal Module (No Dependencies)**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "standalone-module",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/standalone"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Module with Branch Specification**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "beta-module",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/beta",
|
||||||
|
"branch": "develop"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Module with Dependencies**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "mail",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/mail",
|
||||||
|
"branch": "main",
|
||||||
|
"dependencies": ["mail_manager", "provider_jmapc"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
### Single Module
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "auth", "repo": "https://git.ktrix.dev/Nodarx/auth"}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linear Dependencies (A → B → C)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "core", "repo": "https://git.ktrix.dev/Nodarx/core"},
|
||||||
|
{"name": "api", "repo": "https://git.ktrix.dev/Nodarx/api", "dependencies": ["core"]},
|
||||||
|
{"name": "web", "repo": "https://git.ktrix.dev/Nodarx/web", "dependencies": ["api"]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
Installation order: `core` → `api` → `web`
|
||||||
|
|
||||||
|
### Diamond Dependencies (A,B → C; C → D)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "utils", "repo": "https://git.ktrix.dev/Nodarx/utils"},
|
||||||
|
{"name": "storage", "repo": "https://git.ktrix.dev/Nodarx/storage"},
|
||||||
|
{"name": "database", "repo": "https://git.ktrix.dev/Nodarx/database", "dependencies": ["utils", "storage"]},
|
||||||
|
{"name": "api", "repo": "https://git.ktrix.dev/Nodarx/api", "dependencies": ["database"]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
Installation order: `utils,storage` → `database` → `api`
|
||||||
|
|
||||||
|
### Mail System Example (Real-World)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-server-install@v1
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
node-version: '24'
|
||||||
|
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
id: modules
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "mail_manager",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/mail_manager",
|
||||||
|
"branch": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "provider_jmapc",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/provider_jmapc",
|
||||||
|
"branch": "stable1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mail",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/mail",
|
||||||
|
"branch": "main",
|
||||||
|
"dependencies": ["mail_manager", "provider_jmapc"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
install-path: './modules'
|
||||||
|
|
||||||
|
- name: Verify installation
|
||||||
|
run: |
|
||||||
|
echo "Installed: ${{ steps.modules.outputs.installed-modules }}"
|
||||||
|
ls -la ./modules/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Different Branches per Module
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "core", "repo": "https://git.ktrix.dev/Nodarx/core", "branch": "v2.0"},
|
||||||
|
{"name": "plugin", "repo": "https://git.ktrix.dev/Nodarx/plugin", "branch": "develop"},
|
||||||
|
{"name": "theme", "repo": "https://git.ktrix.dev/Nodarx/theme", "branch": "stable1"}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Install Path
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
install-path: './custom/modules/directory'
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{"name": "module1", "repo": "https://git.ktrix.dev/Nodarx/module1"}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. **Validation**: Validates JSON structure and checks that all dependencies are defined
|
||||||
|
2. **Dependency Resolution**: Uses topological sort to determine correct installation order
|
||||||
|
3. **Cloning**: Clones each module repository in dependency order
|
||||||
|
4. **Installation**: Auto-detects and runs:
|
||||||
|
- `composer install` for modules with `composer.json`
|
||||||
|
- `npm install` or `npm ci` for modules with `package.json`
|
||||||
|
5. **Verification**: Verifies all modules installed successfully
|
||||||
|
|
||||||
|
## Dependency Resolution
|
||||||
|
|
||||||
|
The action automatically determines the correct installation order:
|
||||||
|
|
||||||
|
```
|
||||||
|
Input modules:
|
||||||
|
- mail (depends on: mail_manager, provider_jmapc)
|
||||||
|
- mail_manager (no dependencies)
|
||||||
|
- provider_jmapc (no dependencies)
|
||||||
|
|
||||||
|
Installation order:
|
||||||
|
1. mail_manager
|
||||||
|
2. provider_jmapc
|
||||||
|
3. mail
|
||||||
|
```
|
||||||
|
|
||||||
|
Dependencies are installed **before** their dependents, ensuring all required modules are available when needed.
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
The action will fail with descriptive errors for:
|
||||||
|
|
||||||
|
- ❌ **Invalid JSON**: Syntax errors in modules input
|
||||||
|
- ❌ **Missing Fields**: Modules without `name` or `repo`
|
||||||
|
- ❌ **Circular Dependencies**: A → B → A
|
||||||
|
- ❌ **Missing Dependencies**: Module depends on undefined module
|
||||||
|
- ❌ **Clone Failures**: Repository not accessible or branch doesn't exist
|
||||||
|
- ❌ **Install Failures**: Composer or npm installation errors
|
||||||
|
- ❌ **Missing Prerequisites**: PHP/Composer or Node/npm not installed
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before using this action, ensure PHP and/or Node.js are installed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-server-install@v1
|
||||||
|
with:
|
||||||
|
install-php: 'true' # If modules use Composer
|
||||||
|
install-node: 'true' # If modules use npm
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use standard setup actions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '24'
|
||||||
|
|
||||||
|
- uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: '8.5'
|
||||||
|
tools: composer:v2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Circular Dependency Error
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: Circular dependency detected. Cannot determine installation order.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: Review your dependencies to remove circular references. Example:
|
||||||
|
```
|
||||||
|
❌ moduleA depends on moduleB, moduleB depends on moduleA
|
||||||
|
✅ moduleA depends on moduleB, moduleB has no dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
### Missing Dependency Error
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: The following dependencies are referenced but not defined: module_x
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: Add the missing module to your modules array:
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{"name": "module_x", "repo": "https://..."},
|
||||||
|
{"name": "dependent", "repo": "https://...", "dependencies": ["module_x"]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Composer/npm Not Found
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: composer not found. Please ensure PHP and Composer are installed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: Install PHP/Node.js before this action:
|
||||||
|
```yaml
|
||||||
|
- uses: Nodarx/action-server-install@v1
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clone Failed (Branch Not Found)
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: Failed to clone module_name from https://... (branch: xyz)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Solution**: Verify the branch exists in the repository. Use `main`, `master`, or a valid branch/tag name.
|
||||||
|
|
||||||
|
## Complete Workflow Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Deploy Application with Modules
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup server environment
|
||||||
|
uses: Nodarx/action-server-install@v1
|
||||||
|
with:
|
||||||
|
install-php: 'true'
|
||||||
|
install-node: 'true'
|
||||||
|
php-version: '8.5'
|
||||||
|
node-version: '24'
|
||||||
|
server-path: './server'
|
||||||
|
|
||||||
|
- name: Install application modules
|
||||||
|
id: install-modules
|
||||||
|
uses: Nodarx/action-module-install@v1
|
||||||
|
with:
|
||||||
|
modules: |
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "mail_manager",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/mail_manager",
|
||||||
|
"branch": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "provider_jmapc",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/provider_jmapc",
|
||||||
|
"branch": "stable1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mail",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/mail",
|
||||||
|
"branch": "main",
|
||||||
|
"dependencies": ["mail_manager", "provider_jmapc"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "calendar",
|
||||||
|
"repo": "https://git.ktrix.dev/Nodarx/calendar",
|
||||||
|
"branch": "main",
|
||||||
|
"dependencies": ["mail_manager"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
install-path: './server/modules'
|
||||||
|
|
||||||
|
- name: Display installation results
|
||||||
|
run: |
|
||||||
|
echo "Installation Status: ${{ steps.install-modules.outputs.status }}"
|
||||||
|
echo "Installed Modules: ${{ steps.install-modules.outputs.installed-modules }}"
|
||||||
|
echo "Install Path: ${{ steps.install-modules.outputs.install-path }}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Module directories:"
|
||||||
|
ls -la ${{ steps.install-modules.outputs.install-path }}
|
||||||
|
|
||||||
|
- name: Run application tests
|
||||||
|
run: |
|
||||||
|
cd ./server
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - see [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
Created by [Nodarx](https://github.com/Nodarx)
|
||||||
|
|
||||||
|
|||||||
414
action.yml
Normal file
414
action.yml
Normal file
@@ -0,0 +1,414 @@
|
|||||||
|
name: 'Install Nodarx Modules'
|
||||||
|
description: 'Installs custom PHP/Vue modules from git repositories with dependency resolution'
|
||||||
|
author: 'Nodarx'
|
||||||
|
|
||||||
|
branding:
|
||||||
|
icon: 'package'
|
||||||
|
color: 'purple'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
modules:
|
||||||
|
description: 'JSON array of modules to install. Example: [{"name":"mail","repo":"https://git.ktrix.dev/Nodarx/mail","branch":"main","dependencies":["mail_manager"]}]'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
install-path:
|
||||||
|
description: 'Base directory where modules will be installed'
|
||||||
|
required: false
|
||||||
|
default: './modules'
|
||||||
|
|
||||||
|
skip-dependencies-check:
|
||||||
|
description: 'Skip dependency validation (not recommended)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
installed-modules:
|
||||||
|
description: 'Comma-separated list of installed module names in installation order'
|
||||||
|
value: ${{ steps.install.outputs.installed_modules }}
|
||||||
|
|
||||||
|
install-path:
|
||||||
|
description: 'Path where modules were installed'
|
||||||
|
value: ${{ steps.install.outputs.install_path }}
|
||||||
|
|
||||||
|
status:
|
||||||
|
description: 'Installation status (success/failure)'
|
||||||
|
value: ${{ steps.install.outputs.status }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'composite'
|
||||||
|
steps:
|
||||||
|
- name: Check prerequisites
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "::group::Checking prerequisites"
|
||||||
|
|
||||||
|
# Check for required commands
|
||||||
|
MISSING_CMDS=()
|
||||||
|
for cmd in git jq; do
|
||||||
|
if ! command -v $cmd &> /dev/null; then
|
||||||
|
MISSING_CMDS+=($cmd)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install missing commands
|
||||||
|
if [ ${#MISSING_CMDS[@]} -gt 0 ]; then
|
||||||
|
echo "Installing missing commands: ${MISSING_CMDS[*]}"
|
||||||
|
sudo apt-get update -qq
|
||||||
|
for cmd in "${MISSING_CMDS[@]}"; do
|
||||||
|
sudo apt-get install -y $cmd
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify all commands are now available
|
||||||
|
for cmd in git jq; do
|
||||||
|
if ! command -v $cmd &> /dev/null; then
|
||||||
|
echo "::error::Required command '$cmd' not found after installation attempt."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✓ All prerequisites met"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Validate and parse modules JSON
|
||||||
|
id: parse
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MODULES_JSON: ${{ inputs.modules }}
|
||||||
|
SKIP_DEPS_CHECK: ${{ inputs.skip-dependencies-check }}
|
||||||
|
run: |
|
||||||
|
echo "::group::Validating modules configuration"
|
||||||
|
|
||||||
|
# Validate JSON syntax
|
||||||
|
if ! echo "$MODULES_JSON" | jq empty 2>/dev/null; then
|
||||||
|
echo "::error::Invalid JSON in modules input"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate JSON is an array
|
||||||
|
if [ "$(echo "$MODULES_JSON" | jq 'type')" != '"array"' ]; then
|
||||||
|
echo "::error::Modules input must be a JSON array"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if array is empty
|
||||||
|
MODULE_COUNT=$(echo "$MODULES_JSON" | jq 'length')
|
||||||
|
if [ "$MODULE_COUNT" -eq 0 ]; then
|
||||||
|
echo "::error::Modules array is empty. Please specify at least one module."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Found $MODULE_COUNT module(s) to install"
|
||||||
|
|
||||||
|
# Validate each module has required fields
|
||||||
|
INVALID_MODULES=$(echo "$MODULES_JSON" | jq -r '
|
||||||
|
to_entries[] |
|
||||||
|
select(.value.name == null or .value.name == "" or .value.repo == null or .value.repo == "") |
|
||||||
|
.key
|
||||||
|
')
|
||||||
|
|
||||||
|
if [ -n "$INVALID_MODULES" ]; then
|
||||||
|
echo "::error::Modules at indices $INVALID_MODULES are missing required fields 'name' or 'repo'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract all module names
|
||||||
|
ALL_MODULES=$(echo "$MODULES_JSON" | jq -r '.[].name' | tr '\n' ' ')
|
||||||
|
echo "Modules to install: $ALL_MODULES"
|
||||||
|
|
||||||
|
# Validate dependencies exist (if not skipped)
|
||||||
|
if [ "$SKIP_DEPS_CHECK" != "true" ]; then
|
||||||
|
MISSING_DEPS=$(echo "$MODULES_JSON" | jq -r --arg all_modules "$ALL_MODULES" '
|
||||||
|
.[] |
|
||||||
|
select(.dependencies != null) |
|
||||||
|
.dependencies[] as $dep |
|
||||||
|
select(($all_modules | contains($dep)) | not) |
|
||||||
|
$dep
|
||||||
|
' | sort -u)
|
||||||
|
|
||||||
|
if [ -n "$MISSING_DEPS" ]; then
|
||||||
|
echo "::error::The following dependencies are referenced but not defined: $MISSING_DEPS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✓ Modules configuration is valid"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Order modules by dependencies
|
||||||
|
id: order
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MODULES_JSON: ${{ inputs.modules }}
|
||||||
|
SKIP_DEPS_CHECK: ${{ inputs.skip-dependencies-check }}
|
||||||
|
run: |
|
||||||
|
echo "::group::Calculating installation order"
|
||||||
|
|
||||||
|
# Create temporary files for topological sort
|
||||||
|
TEMP_DIR=$(mktemp -d)
|
||||||
|
EDGES_FILE="$TEMP_DIR/edges"
|
||||||
|
NODES_FILE="$TEMP_DIR/nodes"
|
||||||
|
|
||||||
|
# Extract all module names
|
||||||
|
echo "$MODULES_JSON" | jq -r '.[].name' > "$NODES_FILE"
|
||||||
|
|
||||||
|
# Create dependency edges (dependent -> dependency)
|
||||||
|
# For each module with dependencies, create "module dep" pairs
|
||||||
|
echo "$MODULES_JSON" | jq -r '
|
||||||
|
.[] |
|
||||||
|
select(.dependencies != null and (.dependencies | length) > 0) |
|
||||||
|
. as $item |
|
||||||
|
.dependencies[] |
|
||||||
|
($item.name + " " + .)
|
||||||
|
' > "$EDGES_FILE"
|
||||||
|
|
||||||
|
# Perform topological sort
|
||||||
|
if [ "$SKIP_DEPS_CHECK" != "true" ] && [ -s "$EDGES_FILE" ]; then
|
||||||
|
# Check for circular dependencies
|
||||||
|
if ! tsort "$EDGES_FILE" &>/dev/null; then
|
||||||
|
echo "::error::Circular dependency detected. Cannot determine installation order."
|
||||||
|
cat "$EDGES_FILE"
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get sorted order (reverse tsort output since it gives reverse topological order)
|
||||||
|
INSTALL_ORDER=$(cat "$NODES_FILE" "$EDGES_FILE" | tsort | tac | tr '\n' ' ')
|
||||||
|
else
|
||||||
|
# No dependencies or skip check - install in order given
|
||||||
|
INSTALL_ORDER=$(cat "$NODES_FILE" | tr '\n' ' ')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
|
||||||
|
echo "Installation order: $INSTALL_ORDER"
|
||||||
|
echo "install_order=$INSTALL_ORDER" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
echo "✓ Installation order determined"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Clone module repositories
|
||||||
|
id: clone
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
MODULES_JSON: ${{ inputs.modules }}
|
||||||
|
INSTALL_PATH: ${{ inputs.install-path }}
|
||||||
|
INSTALL_ORDER: ${{ steps.order.outputs.install_order }}
|
||||||
|
run: |
|
||||||
|
echo "::group::Cloning module repositories"
|
||||||
|
|
||||||
|
# Create base install directory
|
||||||
|
mkdir -p "$INSTALL_PATH"
|
||||||
|
|
||||||
|
# Clone each module in order
|
||||||
|
for MODULE_NAME in $INSTALL_ORDER; do
|
||||||
|
echo ""
|
||||||
|
echo "=== Cloning module: $MODULE_NAME ==="
|
||||||
|
|
||||||
|
# Extract module info from JSON
|
||||||
|
MODULE_INFO=$(echo "$MODULES_JSON" | jq -r --arg name "$MODULE_NAME" '
|
||||||
|
.[] | select(.name == $name)
|
||||||
|
')
|
||||||
|
|
||||||
|
REPO_URL=$(echo "$MODULE_INFO" | jq -r '.repo')
|
||||||
|
BRANCH=$(echo "$MODULE_INFO" | jq -r '.branch // empty')
|
||||||
|
MODULE_PATH="$INSTALL_PATH/$MODULE_NAME"
|
||||||
|
|
||||||
|
echo "Repository: $REPO_URL"
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
echo "Branch: $BRANCH"
|
||||||
|
else
|
||||||
|
echo "Branch: (repository default)"
|
||||||
|
fi
|
||||||
|
echo "Path: $MODULE_PATH"
|
||||||
|
|
||||||
|
# Clone the repository
|
||||||
|
if [ -d "$MODULE_PATH" ]; then
|
||||||
|
echo "::warning::Directory $MODULE_PATH already exists, pulling latest changes..."
|
||||||
|
cd "$MODULE_PATH"
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
git pull origin "$BRANCH" || echo "::warning::Pull failed, continuing with existing code"
|
||||||
|
else
|
||||||
|
git pull || echo "::warning::Pull failed, continuing with existing code"
|
||||||
|
fi
|
||||||
|
cd - > /dev/null
|
||||||
|
else
|
||||||
|
if [ -n "$BRANCH" ]; then
|
||||||
|
if git clone --branch "$BRANCH" --depth 1 "$REPO_URL" "$MODULE_PATH"; then
|
||||||
|
echo "✓ Cloned $MODULE_NAME successfully"
|
||||||
|
else
|
||||||
|
echo "::error::Failed to clone $MODULE_NAME from $REPO_URL (branch: $BRANCH)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if git clone --depth 1 "$REPO_URL" "$MODULE_PATH"; then
|
||||||
|
echo "✓ Cloned $MODULE_NAME successfully"
|
||||||
|
else
|
||||||
|
echo "::error::Failed to clone $MODULE_NAME from $REPO_URL"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✓ All modules cloned successfully"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Install module dependencies
|
||||||
|
id: install
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
INSTALL_PATH: ${{ inputs.install-path }}
|
||||||
|
INSTALL_ORDER: ${{ steps.order.outputs.install_order }}
|
||||||
|
run: |
|
||||||
|
echo "::group::Installing module dependencies"
|
||||||
|
|
||||||
|
INSTALLED_MODULES=()
|
||||||
|
|
||||||
|
for MODULE_NAME in $INSTALL_ORDER; do
|
||||||
|
MODULE_PATH="$INSTALL_PATH/$MODULE_NAME"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Installing dependencies for: $MODULE_NAME ==="
|
||||||
|
echo "Path: $MODULE_PATH"
|
||||||
|
|
||||||
|
if [ ! -d "$MODULE_PATH" ]; then
|
||||||
|
echo "::error::Module directory not found: $MODULE_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$MODULE_PATH"
|
||||||
|
|
||||||
|
# Detect and install PHP dependencies
|
||||||
|
if [ -f "composer.json" ]; then
|
||||||
|
echo "Found composer.json - installing PHP dependencies..."
|
||||||
|
|
||||||
|
# Check if composer is available
|
||||||
|
if ! command -v composer &> /dev/null; then
|
||||||
|
echo "::error::composer not found. Please ensure PHP and Composer are installed (use action-server-install with install-php: true)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install with composer
|
||||||
|
if composer install --no-dev --optimize-autoloader --no-interaction; then
|
||||||
|
echo "✓ Composer dependencies installed"
|
||||||
|
else
|
||||||
|
echo "::error::Failed to install composer dependencies for $MODULE_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "No composer.json found, skipping PHP dependencies"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect and install Node dependencies
|
||||||
|
if [ -f "package.json" ]; then
|
||||||
|
echo "Found package.json - installing Node dependencies..."
|
||||||
|
|
||||||
|
# Check if npm is available
|
||||||
|
if ! command -v npm &> /dev/null; then
|
||||||
|
echo "::error::npm not found. Please ensure Node.js is installed (use action-server-install with install-node: true)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use npm ci if lockfile exists, otherwise npm install
|
||||||
|
if [ -f "package-lock.json" ]; then
|
||||||
|
echo "Using npm ci (lockfile found)..."
|
||||||
|
if npm ci --production; then
|
||||||
|
echo "✓ npm dependencies installed (with lockfile)"
|
||||||
|
else
|
||||||
|
echo "::warning::npm ci failed, trying npm install..."
|
||||||
|
if npm install --production; then
|
||||||
|
echo "✓ npm dependencies installed"
|
||||||
|
else
|
||||||
|
echo "::error::Failed to install npm dependencies for $MODULE_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Using npm install (no lockfile)..."
|
||||||
|
if npm install --production; then
|
||||||
|
echo "✓ npm dependencies installed"
|
||||||
|
else
|
||||||
|
echo "::error::Failed to install npm dependencies for $MODULE_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "No package.json found, skipping Node dependencies"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return to previous directory
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
INSTALLED_MODULES+=("$MODULE_NAME")
|
||||||
|
echo "✓ $MODULE_NAME installation complete"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Set outputs
|
||||||
|
INSTALLED_LIST=$(IFS=,; echo "${INSTALLED_MODULES[*]}")
|
||||||
|
echo "installed_modules=$INSTALLED_LIST" >> $GITHUB_OUTPUT
|
||||||
|
echo "install_path=$INSTALL_PATH" >> $GITHUB_OUTPUT
|
||||||
|
echo "status=success" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "::notice::✓ Successfully installed ${#INSTALLED_MODULES[@]} module(s): $INSTALLED_LIST"
|
||||||
|
echo "::endgroup::"
|
||||||
|
|
||||||
|
- name: Verify installations
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
INSTALL_PATH: ${{ inputs.install-path }}
|
||||||
|
INSTALL_ORDER: ${{ steps.order.outputs.install_order }}
|
||||||
|
run: |
|
||||||
|
echo "::group::Verifying module installations"
|
||||||
|
|
||||||
|
for MODULE_NAME in $INSTALL_ORDER; do
|
||||||
|
MODULE_PATH="$INSTALL_PATH/$MODULE_NAME"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Verifying: $MODULE_NAME"
|
||||||
|
|
||||||
|
# Check module directory exists
|
||||||
|
if [ ! -d "$MODULE_PATH" ]; then
|
||||||
|
echo "::error::Module directory not found: $MODULE_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check .git directory exists
|
||||||
|
if [ ! -d "$MODULE_PATH/.git" ]; then
|
||||||
|
echo "::warning::No .git directory found in $MODULE_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify composer installation
|
||||||
|
if [ -f "$MODULE_PATH/composer.json" ]; then
|
||||||
|
if [ -d "$MODULE_PATH/vendor" ]; then
|
||||||
|
echo " ✓ PHP dependencies installed (vendor/ exists)"
|
||||||
|
else
|
||||||
|
echo "::error::composer.json exists but vendor/ directory not found in $MODULE_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify npm installation
|
||||||
|
if [ -f "$MODULE_PATH/package.json" ]; then
|
||||||
|
NODE_DEP_COUNT=$(jq -r '((.dependencies // {}) | length) + ((.optionalDependencies // {}) | length)' "$MODULE_PATH/package.json" 2>/dev/null || echo "0")
|
||||||
|
if [ "$NODE_DEP_COUNT" -gt 0 ]; then
|
||||||
|
if [ -d "$MODULE_PATH/node_modules" ]; then
|
||||||
|
echo " ✓ Node dependencies installed (node_modules/ exists)"
|
||||||
|
else
|
||||||
|
echo "::error::package.json has production dependencies but node_modules/ directory not found in $MODULE_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " ✓ Node module has no production dependencies (node_modules/ not required)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " ✓ $MODULE_NAME verified"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✓ All modules verified successfully"
|
||||||
|
echo "::endgroup::"
|
||||||
Reference in New Issue
Block a user