Compare commits

...

11 Commits

Author SHA1 Message Date
bahdotsh
5051f71b8b Release 0.7.1
wrkflw@0.7.1
wrkflw-evaluator@0.7.1
wrkflw-executor@0.7.1
wrkflw-parser@0.7.1
wrkflw-runtime@0.7.1
wrkflw-secrets@0.7.1
wrkflw-ui@0.7.1

Generated by cargo-workspaces
2025-08-22 13:13:53 +05:30
Gokul
64b980d254 Merge pull request #55 from bahdotsh/fix/ui_logs_for_copy
fix: fix the ui logs from displaying copy logs noise
2025-08-22 12:23:08 +05:30
bahdotsh
2d809388a2 fix: fix the ui logs from displaying copy logs noise 2025-08-22 12:19:16 +05:30
Gokul
03af6cb7c1 Merge pull request #54 from azzamsa/use-rust-tls
build: use `rustls` instead `openssl`
2025-08-22 12:07:37 +05:30
Azzam S.A
ae52779e11 build: use rustls instead openssl
Simplifies local and container builds by removing OpenSSL deps.
2025-08-22 13:25:50 +07:00
Gokul
fe7be3e1ae Merge pull request #53 from bahdotsh/fix/remove-name-field-requirement
fix(evaluator): remove incorrect name field requirement validation
2025-08-21 23:44:17 +05:30
bahdotsh
30f405ccb9 fix(evaluator): remove incorrect name field requirement validation
The 'name' field is optional per GitHub Actions specification. When omitted,
GitHub displays the workflow file path relative to the repository root.

This change removes the validation logic that incorrectly enforced the name
field as required, aligning the validator with the official JSON schema
which only requires 'on' and 'jobs' fields at the root level.

Fixes #50
2025-08-21 22:45:36 +05:30
Gokul
1d56d86ba5 Merge pull request #52 from bahdotsh/fix/ubuntu-container-image-selection
fix: ubuntu container image selection
2025-08-21 22:37:22 +05:30
bahdotsh
f1ca411281 feat(runtime): add dtolnay/rust-toolchain action support
- Add emulation support for dtolnay/rust-toolchain@ actions
- Include Rust and Cargo availability checks for dtolnay toolchain action
- Improve action detection logging for dtolnay Rust toolchain

Related to #49
2025-08-21 22:28:12 +05:30
bahdotsh
797e31e3d3 fix(executor): correct Ubuntu runner image mapping
- Fix get_runner_image() to map ubuntu-latest to ubuntu:latest instead of node:16-buster-slim
- Update ubuntu-22.04, ubuntu-20.04, ubuntu-18.04 to use proper Ubuntu base images
- Fix step execution to use action-specific images instead of always using runner image
- Update Node.js fallback images from node:16-buster-slim to node:20-slim

Fixes #49
2025-08-21 22:27:56 +05:30
Gokul
4e66f65de7 Merge pull request #51 from bahdotsh/feature/gitignore-support
feat: Add .gitignore support for file copying
2025-08-21 15:32:31 +05:30
6 changed files with 524 additions and 502 deletions

930
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.7.0"
version = "0.7.1"
edition = "2021"
description = "A GitHub Actions workflow validator and executor"
documentation = "https://github.com/bahdotsh/wrkflw"
@@ -44,7 +44,7 @@ rayon = "1.7.0"
num_cpus = "1.16.0"
regex = "1.10"
lazy_static = "1.4"
reqwest = { version = "0.11", features = ["json"] }
reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "json"] }
libc = "0.2"
nix = { version = "0.27.1", features = ["fs"] }
urlencoding = "2.1.3"

View File

@@ -21,26 +21,9 @@ pub fn evaluate_workflow_file(path: &Path, verbose: bool) -> Result<ValidationRe
return Ok(result);
}
// Check if name exists
if workflow.get("name").is_none() {
// Check if this might be a reusable workflow caller before reporting missing name
let has_reusable_workflow_job = if let Some(Value::Mapping(jobs)) = workflow.get("jobs") {
jobs.values().any(|job| {
if let Some(job_config) = job.as_mapping() {
job_config.contains_key(Value::String("uses".to_string()))
} else {
false
}
})
} else {
false
};
// Only report missing name if it's not a workflow with reusable workflow jobs
if !has_reusable_workflow_job {
result.add_issue("Workflow is missing a name".to_string());
}
}
// Note: The 'name' field is optional per GitHub Actions specification.
// When omitted, GitHub displays the workflow file path relative to the repository root.
// We do not validate name presence as it's not required by the schema.
// Check if jobs section exists
match workflow.get("jobs") {

View File

@@ -570,7 +570,7 @@ async fn prepare_action(
} else {
// It's a JavaScript or composite action
// For simplicity, we'll use node to run it (this would need more work for full support)
return Ok("node:16-buster-slim".to_string());
return Ok("node:20-slim".to_string());
}
}
@@ -628,7 +628,7 @@ fn determine_action_image(repository: &str) -> String {
{
"catthehacker/ubuntu:act-latest".to_string() // Use act runner image for core actions
} else {
"node:16-buster-slim".to_string() // Default for other actions
"node:20-slim".to_string() // Default for other actions
}
}
}
@@ -1160,28 +1160,13 @@ async fn execute_step(ctx: StepExecutionContext<'_>) -> Result<StepResult, Execu
detailed_output
.push_str(&format!(" - Destination: {}\n", ctx.working_dir.display()));
// Add list of top-level files/directories that were copied (limit to 10)
detailed_output.push_str("\nTop-level files/directories copied:\n");
// Add a summary count instead of listing all files
if let Ok(entries) = std::fs::read_dir(&current_dir) {
for (i, entry) in entries.take(10).enumerate() {
if let Ok(entry) = entry {
let file_type = if entry.path().is_dir() {
"directory"
} else {
"file"
};
detailed_output.push_str(&format!(
" - {} ({})\n",
entry.file_name().to_string_lossy(),
file_type
));
}
if i >= 9 {
detailed_output.push_str(" - ... (more items not shown)\n");
break;
}
}
let entry_count = entries.count();
detailed_output.push_str(&format!(
"\nCopied {} top-level items to workspace\n",
entry_count
));
}
detailed_output
@@ -1224,13 +1209,15 @@ async fn execute_step(ctx: StepExecutionContext<'_>) -> Result<StepResult, Execu
let mut owned_strings: Vec<String> = Vec::new(); // Keep strings alive until after we use cmd
// Special handling for Rust actions
if uses.starts_with("actions-rs/") {
if uses.starts_with("actions-rs/") || uses.starts_with("dtolnay/rust-toolchain") {
wrkflw_logging::info(
"🔄 Detected Rust action - using system Rust installation",
);
// For toolchain action, verify Rust is installed
if uses.starts_with("actions-rs/toolchain@") {
if uses.starts_with("actions-rs/toolchain@")
|| uses.starts_with("dtolnay/rust-toolchain@")
{
let rustc_version = Command::new("rustc")
.arg("--version")
.output()
@@ -1556,7 +1543,7 @@ async fn execute_step(ctx: StepExecutionContext<'_>) -> Result<StepResult, Execu
let output = ctx
.runtime
.run_container(
ctx.runner_image,
&image,
&cmd.to_vec(),
&env_vars,
container_workspace,
@@ -1834,6 +1821,13 @@ fn copy_directory_contents_with_gitignore(
gitignore
};
// Log summary of the copy operation
wrkflw_logging::debug(&format!(
"Copying directory contents from {} to {}",
from.display(),
to.display()
));
for entry in std::fs::read_dir(from)
.map_err(|e| ExecutionError::Execution(format!("Failed to read directory: {}", e)))?
{
@@ -1855,7 +1849,7 @@ fn copy_directory_contents_with_gitignore(
}
}
wrkflw_logging::debug(&format!("Copying entry: {path:?} -> {to:?}"));
// Log individual files only in trace mode (removed verbose per-file logging)
// Additional basic filtering for hidden files (but allow .gitignore and .github)
let file_name = match path.file_name() {
@@ -1905,11 +1899,11 @@ fn copy_directory_contents_with_gitignore(
fn get_runner_image(runs_on: &str) -> String {
// Map GitHub runners to Docker images
match runs_on.trim() {
// ubuntu runners - micro images (minimal size)
"ubuntu-latest" => "node:16-buster-slim",
"ubuntu-22.04" => "node:16-bullseye-slim",
"ubuntu-20.04" => "node:16-buster-slim",
"ubuntu-18.04" => "node:16-buster-slim",
// ubuntu runners - using Ubuntu base images for better compatibility
"ubuntu-latest" => "ubuntu:latest",
"ubuntu-22.04" => "ubuntu:22.04",
"ubuntu-20.04" => "ubuntu:20.04",
"ubuntu-18.04" => "ubuntu:18.04",
// ubuntu runners - medium images (with more tools)
"ubuntu-latest-medium" => "catthehacker/ubuntu:act-latest",

View File

@@ -643,6 +643,15 @@ pub async fn handle_special_action(action: &str) -> Result<(), ContainerError> {
wrkflw_logging::info(&format!("🔄 Detected Rust formatter action: {}", action));
check_command_available("rustfmt", "rustfmt", "rustup component add rustfmt");
} else if action.starts_with("dtolnay/rust-toolchain@") {
// For dtolnay/rust-toolchain action, check for Rust installation
wrkflw_logging::info(&format!(
"🔄 Detected dtolnay Rust toolchain action: {}",
action
));
check_command_available("rustc", "Rust", "https://rustup.rs/");
check_command_available("cargo", "Cargo", "https://rustup.rs/");
} else if action.starts_with("actions/setup-node@") {
// Node.js setup action
wrkflw_logging::info(&format!("🔄 Detected Node.js setup action: {}", action));

View File

@@ -1,6 +1,6 @@
[package]
name = "wrkflw-secrets"
version = "0.7.0"
version = "0.7.1"
edition = "2021"
authors = ["wrkflw contributors"]
description = "Secrets management for wrkflw workflow execution"