Compare commits

...

5 Commits

Author SHA1 Message Date
bahdotsh
8fc6dcaa6c Fix PHP workflow execution issues
- Add automatic Docker image pulling in run_container_inner
- Implement smart container image selection for GitHub actions
- Fix shell command parsing to use bash -c for proper quote/pipe handling
- Map shivammathur/setup-php to composer:latest container
- Support complex commands with quotes, pipes, and substitutions

Fixes issues where:
1. Docker images required manual pulling
2. PHP actions used wrong Node.js containers
3. Commands like 'echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT' failed
2025-08-14 14:22:34 +05:30
bahdotsh
3f7bd30cca workflow update 2025-08-13 18:15:34 +05:30
bahdotsh
960f7486a2 Release 0.7.0
wrkflw@0.7.0
wrkflw-evaluator@0.7.0
wrkflw-executor@0.7.0
wrkflw-github@0.7.0
wrkflw-gitlab@0.7.0
wrkflw-logging@0.7.0
wrkflw-matrix@0.7.0
wrkflw-models@0.7.0
wrkflw-parser@0.7.0
wrkflw-runtime@0.7.0
wrkflw-ui@0.7.0
wrkflw-utils@0.7.0
wrkflw-validators@0.7.0

Generated by cargo-workspaces
2025-08-13 18:07:11 +05:30
bahdotsh
cb936cd1af updated publish script 2025-08-13 17:57:44 +05:30
Gokul
625b8111f1 Merge pull request #38 from bahdotsh/improve-tui-help-tab
feat(ui): enhance TUI help tab with comprehensive documentation and s…
2025-08-13 15:29:22 +05:30
19 changed files with 316 additions and 121 deletions

View File

@@ -42,7 +42,30 @@ jobs:
cargo install git-cliff --force
- name: Generate Changelog
run: git-cliff --latest --output CHANGELOG.md
run: |
# Debug: Show current state
echo "Current ref: ${{ github.ref_name }}"
echo "Input version: ${{ github.event.inputs.version }}"
echo "All tags:"
git tag --sort=-version:refname | head -10
# Generate changelog from the current tag to the previous version tag
CURRENT_TAG="${{ github.event.inputs.version || github.ref_name }}"
PREVIOUS_TAG=$(git tag --sort=-version:refname | grep "^v" | head -2 | tail -1)
echo "Current tag: $CURRENT_TAG"
echo "Previous tag: $PREVIOUS_TAG"
if [ -n "$PREVIOUS_TAG" ] && [ "$PREVIOUS_TAG" != "$CURRENT_TAG" ]; then
echo "Generating changelog for range: $PREVIOUS_TAG..$CURRENT_TAG"
git-cliff --tag "$CURRENT_TAG" "$PREVIOUS_TAG..$CURRENT_TAG" --output CHANGELOG.md
else
echo "Generating latest changelog for tag: $CURRENT_TAG"
git-cliff --tag "$CURRENT_TAG" --latest --output CHANGELOG.md
fi
echo "Generated changelog:"
cat CHANGELOG.md
- name: Create Release
id: create_release

26
Cargo.lock generated
View File

@@ -2545,7 +2545,7 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
name = "wrkflw"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"bollard",
"chrono",
@@ -2592,7 +2592,7 @@ dependencies = [
[[package]]
name = "wrkflw-evaluator"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"colored",
"serde_yaml",
@@ -2602,7 +2602,7 @@ dependencies = [
[[package]]
name = "wrkflw-executor"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"async-trait",
"bollard",
@@ -2632,7 +2632,7 @@ dependencies = [
[[package]]
name = "wrkflw-github"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"lazy_static",
"regex",
@@ -2646,7 +2646,7 @@ dependencies = [
[[package]]
name = "wrkflw-gitlab"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"lazy_static",
"regex",
@@ -2661,7 +2661,7 @@ dependencies = [
[[package]]
name = "wrkflw-logging"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"chrono",
"once_cell",
@@ -2672,7 +2672,7 @@ dependencies = [
[[package]]
name = "wrkflw-matrix"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"indexmap 2.8.0",
"serde",
@@ -2683,7 +2683,7 @@ dependencies = [
[[package]]
name = "wrkflw-models"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"serde",
"serde_json",
@@ -2693,7 +2693,7 @@ dependencies = [
[[package]]
name = "wrkflw-parser"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"jsonschema",
"serde",
@@ -2707,7 +2707,7 @@ dependencies = [
[[package]]
name = "wrkflw-runtime"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"async-trait",
"futures",
@@ -2726,7 +2726,7 @@ dependencies = [
[[package]]
name = "wrkflw-ui"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"chrono",
"crossterm 0.26.1",
@@ -2748,7 +2748,7 @@ dependencies = [
[[package]]
name = "wrkflw-utils"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"nix",
"serde",
@@ -2758,7 +2758,7 @@ dependencies = [
[[package]]
name = "wrkflw-validators"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"serde",
"serde_yaml",

View File

@@ -5,7 +5,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.6.0"
version = "0.7.0"
edition = "2021"
description = "A GitHub Actions workflow validator and executor"
documentation = "https://github.com/bahdotsh/wrkflw"

View File

@@ -12,9 +12,9 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-validators = { path = "../validators", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-validators = { path = "../validators", version = "0.7.0" }
# External dependencies
colored.workspace = true
serde_yaml.workspace = true
serde_yaml.workspace = true

View File

@@ -12,12 +12,12 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-parser = { path = "../parser", version = "0.6.0" }
wrkflw-runtime = { path = "../runtime", version = "0.6.0" }
wrkflw-logging = { path = "../logging", version = "0.6.0" }
wrkflw-matrix = { path = "../matrix", version = "0.6.0" }
wrkflw-utils = { path = "../utils", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-parser = { path = "../parser", version = "0.7.0" }
wrkflw-runtime = { path = "../runtime", version = "0.7.0" }
wrkflw-logging = { path = "../logging", version = "0.7.0" }
wrkflw-matrix = { path = "../matrix", version = "0.7.0" }
wrkflw-utils = { path = "../utils", version = "0.7.0" }
# External dependencies
async-trait.workspace = true

View File

@@ -840,6 +840,14 @@ impl DockerRuntime {
working_dir: &Path,
volumes: &[(&Path, &Path)],
) -> Result<ContainerOutput, ContainerError> {
// First, try to pull the image if it's not available locally
if let Err(e) = self.pull_image_inner(image).await {
wrkflw_logging::warning(&format!(
"Failed to pull image {}: {}. Attempting to continue with existing image.",
image, e
));
}
// Collect environment variables
let mut env: Vec<String> = env_vars
.iter()

View File

@@ -526,9 +526,64 @@ async fn prepare_action(
}
}
// GitHub action: use standard runner image
// In a real implementation, you'd need to clone the repo at the specified version
Ok("node:16-buster-slim".to_string())
// GitHub action: determine appropriate image based on action type
let image = determine_action_image(&action.repository);
Ok(image)
}
/// Determine the appropriate Docker image for a GitHub action
fn determine_action_image(repository: &str) -> String {
// Handle specific well-known actions
match repository {
// PHP setup actions
repo if repo.starts_with("shivammathur/setup-php") => {
"composer:latest".to_string() // Use composer image which includes PHP and composer
}
// Python setup actions
repo if repo.starts_with("actions/setup-python") => "python:3.11-slim".to_string(),
// Node.js setup actions
repo if repo.starts_with("actions/setup-node") => "node:20-slim".to_string(),
// Java setup actions
repo if repo.starts_with("actions/setup-java") => "eclipse-temurin:17-jdk".to_string(),
// Go setup actions
repo if repo.starts_with("actions/setup-go") => "golang:1.21-slim".to_string(),
// .NET setup actions
repo if repo.starts_with("actions/setup-dotnet") => {
"mcr.microsoft.com/dotnet/sdk:7.0".to_string()
}
// Rust setup actions
repo if repo.starts_with("actions-rs/toolchain")
|| repo.starts_with("dtolnay/rust-toolchain") =>
{
"rust:latest".to_string()
}
// Docker/container actions
repo if repo.starts_with("docker/") => "docker:latest".to_string(),
// AWS actions
repo if repo.starts_with("aws-actions/") => "amazon/aws-cli:latest".to_string(),
// Default to Node.js for most GitHub actions (checkout, upload-artifact, etc.)
_ => {
// Check if it's a common core GitHub action that should use a more complete environment
if repository.starts_with("actions/checkout")
|| repository.starts_with("actions/upload-artifact")
|| repository.starts_with("actions/download-artifact")
|| repository.starts_with("actions/cache")
{
"catthehacker/ubuntu:act-latest".to_string() // Use act runner image for core actions
} else {
"node:16-buster-slim".to_string() // Default for other actions
}
}
}
}
async fn execute_job_batch(
@@ -1536,8 +1591,9 @@ async fn execute_step(ctx: StepExecutionContext<'_>) -> Result<StepResult, Execu
// Check if this is a cargo command
let is_cargo_cmd = run.trim().starts_with("cargo");
// Convert command string to array of string slices
let cmd_parts: Vec<&str> = run.split_whitespace().collect();
// For complex shell commands, use bash to execute them properly
// This handles quotes, pipes, redirections, and command substitutions correctly
let cmd_parts = vec!["bash", "-c", run];
// Convert environment variables to the required format
let env_vars: Vec<(&str, &str)> = step_env

View File

@@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
# External dependencies from workspace
serde.workspace = true

View File

@@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
# External dependencies
lazy_static.workspace = true

View File

@@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
# External dependencies
chrono.workspace = true

View File

@@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
# External dependencies
indexmap.workspace = true

View File

@@ -14,4 +14,4 @@ categories.workspace = true
serde.workspace = true
serde_yaml.workspace = true
serde_json.workspace = true
thiserror.workspace = true
thiserror.workspace = true

View File

@@ -12,8 +12,8 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-matrix = { path = "../matrix", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-matrix = { path = "../matrix", version = "0.7.0" }
# External dependencies
jsonschema.workspace = true

View File

@@ -12,8 +12,8 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-logging = { path = "../logging", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-logging = { path = "../logging", version = "0.7.0" }
# External dependencies
async-trait.workspace = true
@@ -23,7 +23,7 @@ serde_yaml.workspace = true
tempfile = "3.9"
tokio.workspace = true
futures = "0.3"
wrkflw-utils = { path = "../utils", version = "0.6.0" }
wrkflw-utils = { path = "../utils", version = "0.7.0" }
which = "4.4"
regex = "1.10"
thiserror = "1.0"

View File

@@ -12,12 +12,12 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-evaluator = { path = "../evaluator", version = "0.6.0" }
wrkflw-executor = { path = "../executor", version = "0.6.0" }
wrkflw-logging = { path = "../logging", version = "0.6.0" }
wrkflw-utils = { path = "../utils", version = "0.6.0" }
wrkflw-github = { path = "../github", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-evaluator = { path = "../evaluator", version = "0.7.0" }
wrkflw-executor = { path = "../executor", version = "0.7.0" }
wrkflw-logging = { path = "../logging", version = "0.7.0" }
wrkflw-utils = { path = "../utils", version = "0.7.0" }
wrkflw-github = { path = "../github", version = "0.7.0" }
# External dependencies
chrono.workspace = true

View File

@@ -12,7 +12,7 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
# External dependencies
serde.workspace = true

View File

@@ -12,8 +12,8 @@ categories.workspace = true
[dependencies]
# Internal crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-matrix = { path = "../matrix", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-matrix = { path = "../matrix", version = "0.7.0" }
# External dependencies
serde.workspace = true

View File

@@ -12,18 +12,18 @@ license.workspace = true
[dependencies]
# Workspace crates
wrkflw-models = { path = "../models", version = "0.6.0" }
wrkflw-executor = { path = "../executor", version = "0.6.0" }
wrkflw-github = { path = "../github", version = "0.6.0" }
wrkflw-gitlab = { path = "../gitlab", version = "0.6.0" }
wrkflw-logging = { path = "../logging", version = "0.6.0" }
wrkflw-matrix = { path = "../matrix", version = "0.6.0" }
wrkflw-parser = { path = "../parser", version = "0.6.0" }
wrkflw-runtime = { path = "../runtime", version = "0.6.0" }
wrkflw-ui = { path = "../ui", version = "0.6.0" }
wrkflw-utils = { path = "../utils", version = "0.6.0" }
wrkflw-validators = { path = "../validators", version = "0.6.0" }
wrkflw-evaluator = { path = "../evaluator", version = "0.6.0" }
wrkflw-models = { path = "../models", version = "0.7.0" }
wrkflw-executor = { path = "../executor", version = "0.7.0" }
wrkflw-github = { path = "../github", version = "0.7.0" }
wrkflw-gitlab = { path = "../gitlab", version = "0.7.0" }
wrkflw-logging = { path = "../logging", version = "0.7.0" }
wrkflw-matrix = { path = "../matrix", version = "0.7.0" }
wrkflw-parser = { path = "../parser", version = "0.7.0" }
wrkflw-runtime = { path = "../runtime", version = "0.7.0" }
wrkflw-ui = { path = "../ui", version = "0.7.0" }
wrkflw-utils = { path = "../utils", version = "0.7.0" }
wrkflw-validators = { path = "../validators", version = "0.7.0" }
wrkflw-evaluator = { path = "../evaluator", version = "0.7.0" }
# External dependencies
clap.workspace = true
@@ -62,4 +62,4 @@ path = "src/lib.rs"
[[bin]]
name = "wrkflw"
path = "src/main.rs"
path = "src/main.rs"

View File

@@ -1,71 +1,179 @@
#!/bin/bash
# Simple script to publish all wrkflw crates to crates.io in dependency order
# Enhanced script to manage versions and publish all wrkflw crates using cargo-workspaces
set -e
DRY_RUN=${1:-""}
# Parse command line arguments
COMMAND=${1:-""}
VERSION_TYPE=${2:-""}
DRY_RUN=""
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "🧪 DRY RUN: Testing wrkflw crates publication"
else
echo "🚀 Publishing wrkflw crates to crates.io"
fi
show_help() {
echo "Usage: $0 <command> [options]"
echo ""
echo "Commands:"
echo " version <type> Update versions across workspace"
echo " Types: patch, minor, major"
echo " publish Publish all crates to crates.io"
echo " release <type> Update versions and publish (combines version + publish)"
echo " help Show this help message"
echo ""
echo "Options:"
echo " --dry-run Test without making changes (for publish/release)"
echo ""
echo "Examples:"
echo " $0 version minor # Bump to 0.7.0"
echo " $0 publish --dry-run # Test publishing"
echo " $0 release minor --dry-run # Test version bump + publish"
echo " $0 release patch # Release patch version"
}
# Check if we're logged in to crates.io
if [ ! -f ~/.cargo/credentials.toml ] && [ ! -f ~/.cargo/credentials ]; then
echo "❌ Not logged in to crates.io. Please run: cargo login <your-token>"
exit 1
fi
# Publication order (respecting dependencies)
CRATES=(
"models"
"logging"
"utils"
"matrix"
"validators"
"github"
"gitlab"
"parser"
"runtime"
"evaluator"
"executor"
"ui"
"wrkflw"
)
echo "📦 Publishing crates in dependency order..."
for crate in "${CRATES[@]}"; do
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "Testing $crate..."
cd "crates/$crate"
cargo publish --dry-run --allow-dirty
echo "$crate dry-run successful"
else
echo "Publishing $crate..."
cd "crates/$crate"
cargo publish --allow-dirty
echo "✅ Published $crate"
fi
cd - > /dev/null
# Small delay to avoid rate limiting (except for the last crate and in dry-run)
if [[ "$crate" != "wrkflw" ]] && [[ "$DRY_RUN" != "--dry-run" ]]; then
echo " Waiting 10 seconds to avoid rate limits..."
sleep 10
# Parse dry-run flag from any position
for arg in "$@"; do
if [[ "$arg" == "--dry-run" ]]; then
DRY_RUN="--dry-run"
fi
done
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "🎉 All crates passed dry-run tests!"
echo ""
echo "To actually publish, run:"
echo " ./publish_crates.sh"
else
echo "🎉 All crates published successfully!"
echo ""
echo "Users can now install wrkflw with:"
echo " cargo install wrkflw"
case "$COMMAND" in
"help"|"-h"|"--help"|"")
show_help
exit 0
;;
"version")
if [[ -z "$VERSION_TYPE" ]]; then
echo "❌ Error: Version type required (patch, minor, major)"
echo ""
show_help
exit 1
fi
;;
"publish")
# publish command doesn't need version type
;;
"release")
if [[ -z "$VERSION_TYPE" ]]; then
echo "❌ Error: Version type required for release (patch, minor, major)"
echo ""
show_help
exit 1
fi
;;
*)
echo "❌ Error: Unknown command '$COMMAND'"
echo ""
show_help
exit 1
;;
esac
# Check if cargo-workspaces is installed
if ! command -v cargo-workspaces &> /dev/null; then
echo "❌ cargo-workspaces not found. Installing..."
cargo install cargo-workspaces
fi
# Check if we're logged in to crates.io (only for publish operations)
if [[ "$COMMAND" == "publish" ]] || [[ "$COMMAND" == "release" ]]; then
if [ ! -f ~/.cargo/credentials.toml ] && [ ! -f ~/.cargo/credentials ]; then
echo "❌ Not logged in to crates.io. Please run: cargo login <your-token>"
exit 1
fi
fi
# Function to update versions
update_versions() {
local version_type=$1
echo "🔄 Updating workspace versions ($version_type)..."
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "🧪 DRY RUN: Simulating version update"
echo ""
echo "Current workspace version: $(grep '^version =' Cargo.toml | cut -d'"' -f2)"
echo "Would execute: cargo workspaces version $version_type"
echo ""
echo "This would update all crates and their internal dependencies."
echo "✅ Version update simulation completed (no changes made)"
else
cargo workspaces version "$version_type"
echo "✅ Versions updated successfully"
fi
}
# Function to test build
test_build() {
echo "🔨 Testing workspace build..."
if cargo build --workspace; then
echo "✅ Workspace builds successfully"
else
echo "❌ Build failed. Please fix errors before publishing."
exit 1
fi
}
# Function to publish crates
publish_crates() {
echo "📦 Publishing crates to crates.io..."
if [[ "$DRY_RUN" == "--dry-run" ]]; then
echo "🧪 DRY RUN: Testing publication"
cargo workspaces publish --dry-run
echo "✅ All crates passed dry-run tests!"
echo ""
echo "To actually publish, run:"
echo " $0 publish"
else
cargo workspaces publish
echo "🎉 All crates published successfully!"
echo ""
echo "Users can now install wrkflw with:"
echo " cargo install wrkflw"
fi
}
# Function to show changelog info
show_changelog_info() {
echo "📝 Changelog will be generated automatically by GitHub Actions workflow"
}
# Execute commands based on the operation
case "$COMMAND" in
"version")
update_versions "$VERSION_TYPE"
show_changelog_info
;;
"publish")
test_build
publish_crates
;;
"release")
echo "🚀 Starting release process..."
echo ""
# Step 1: Update versions
update_versions "$VERSION_TYPE"
# Step 2: Test build
test_build
# Step 3: Show changelog info
show_changelog_info
# Step 4: Publish (if not dry-run)
if [[ "$DRY_RUN" != "--dry-run" ]]; then
echo ""
read -p "🤔 Continue with publishing? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
publish_crates
else
echo "⏸️ Publishing cancelled. To publish later, run:"
echo " $0 publish"
fi
else
echo ""
publish_crates
fi
;;
esac