feat: add GitLab pipeline integration

This commit is contained in:
bahdotsh
2025-04-25 15:32:04 +05:30
parent 0c5460e6ea
commit fb1c636971
4 changed files with 93 additions and 28 deletions

7
Cargo.lock generated
View File

@@ -2137,6 +2137,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf16_iter"
version = "1.0.5"
@@ -2542,6 +2548,7 @@ dependencies = [
"tempfile",
"thiserror",
"tokio",
"urlencoding",
"uuid",
"which",
]

View File

@@ -42,6 +42,7 @@ lazy_static = "1.4"
reqwest = { version = "0.11", features = ["json"] }
libc = "0.2"
nix = { version = "0.27.1", features = ["fs"] }
urlencoding = "2.1.3"
[profile.release]
codegen-units = 1

View File

@@ -28,7 +28,7 @@ WRKFLW is a powerful command-line tool for validating and executing GitHub Actio
- **Special Action Handling**: Native handling for commonly used actions like `actions/checkout`
- **Output Capturing**: View logs, step outputs, and execution details
- **Parallel Job Execution**: Runs independent jobs in parallel for faster workflow execution
- **Trigger Workflows Remotely**: Manually trigger workflow runs on GitHub
- **Trigger Workflows Remotely**: Manually trigger workflow runs on GitHub or GitLab
## Installation
@@ -113,6 +113,9 @@ wrkflw tui --emulate
```bash
# Trigger a workflow remotely on GitHub
wrkflw trigger workflow-name --branch main --input key1=value1 --input key2=value2
# Trigger a pipeline remotely on GitLab
wrkflw trigger-gitlab --branch main --variable key1=value1 --variable key2=value2
```
## TUI Controls
@@ -233,6 +236,7 @@ WRKFLW automatically cleans up any Docker containers created during workflow exe
- ✅ Local actions
- ✅ Special handling for common actions (e.g., `actions/checkout`)
- ✅ Workflow triggering via `workflow_dispatch`
- ✅ GitLab pipeline triggering
- ✅ Environment files (`GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STEP_SUMMARY`)
### Limited or Unsupported Features

View File

@@ -2,6 +2,7 @@ mod cleanup_test;
mod evaluator;
mod executor;
mod github;
mod gitlab;
mod logging;
mod matrix;
mod matrix_test;
@@ -87,6 +88,17 @@ enum Commands {
input: Option<Vec<(String, String)>>,
},
/// Trigger a GitLab pipeline remotely
TriggerGitlab {
/// Branch to run the pipeline on
#[arg(short, long)]
branch: Option<String>,
/// Key-value variables for the pipeline in format key=value
#[arg(short, long, value_parser = parse_key_val)]
variable: Option<Vec<(String, String)>>,
},
/// List available workflows
List,
}
@@ -350,17 +362,17 @@ async fn main() {
branch,
input,
}) => {
let inputs = input.as_ref().map(|kv_pairs| {
kv_pairs
.iter()
.cloned()
logging::info(&format!("Triggering workflow {} on GitHub", workflow));
// Convert inputs to HashMap
let input_map = input.as_ref().map(|i| {
i.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<HashMap<String, String>>()
});
match github::trigger_workflow(workflow, branch.as_deref(), inputs.clone()).await {
Ok(_) => {
// Success is already reported in the github module with detailed info
}
match github::trigger_workflow(workflow, branch.as_deref(), input_map).await {
Ok(_) => logging::info("Workflow triggered successfully"),
Err(e) => {
eprintln!("Error triggering workflow: {}", e);
std::process::exit(1);
@@ -368,29 +380,70 @@ async fn main() {
}
}
Some(Commands::List) => match github::get_repo_info() {
Ok(repo_info) => match github::list_workflows(&repo_info).await {
Ok(workflows) => {
if workflows.is_empty() {
println!("No workflows found in the .github/workflows directory");
} else {
println!("Available workflows:");
for workflow in workflows {
println!(" {}", workflow);
}
println!("\nTrigger a workflow with: wrkflw trigger <workflow> [options]");
}
}
Some(Commands::TriggerGitlab { branch, variable }) => {
logging::info("Triggering pipeline on GitLab");
// Convert variables to HashMap
let variable_map = variable.as_ref().map(|v| {
v.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<HashMap<String, String>>()
});
match gitlab::trigger_pipeline(branch.as_deref(), variable_map).await {
Ok(_) => logging::info("GitLab pipeline triggered successfully"),
Err(e) => {
eprintln!("Error listing workflows: {}", e);
eprintln!("Error triggering GitLab pipeline: {}", e);
std::process::exit(1);
}
},
Err(e) => {
eprintln!("Error getting repository info: {}", e);
std::process::exit(1);
}
},
}
Some(Commands::List) => {
logging::info("Listing available workflows");
// Attempt to get GitHub repo info
if let Ok(repo_info) = github::get_repo_info() {
match github::list_workflows(&repo_info).await {
Ok(workflows) => {
if workflows.is_empty() {
println!("No GitHub workflows found in repository");
} else {
println!("GitHub workflows:");
for workflow in workflows {
println!(" {}", workflow);
}
}
}
Err(e) => {
eprintln!("Error listing GitHub workflows: {}", e);
}
}
} else {
println!("Not a GitHub repository or unable to get repository information");
}
// Attempt to get GitLab repo info
if let Ok(repo_info) = gitlab::get_repo_info() {
match gitlab::list_pipelines(&repo_info).await {
Ok(pipelines) => {
if pipelines.is_empty() {
println!("No GitLab pipelines found in repository");
} else {
println!("GitLab pipelines:");
for pipeline in pipelines {
println!(" {}", pipeline);
}
}
}
Err(e) => {
eprintln!("Error listing GitLab pipelines: {}", e);
}
}
} else {
println!("Not a GitLab repository or unable to get repository information");
}
}
None => {
// Default to TUI interface if no subcommand