pub struct Context;Expand description
Typed, lazily-read accessors for the workflow run context.
This is a zero-sized handle; every method reads the corresponding
environment variable on call, so values reflect the current process
environment. Per the design decision, the webhook payload is exposed only
as the path (Context::event_path) — parsing the JSON would require a
serde dependency and is out of scope.
§Examples
let ctx = actions_rs::Context::new();
// Each accessor is `Option`: `None` outside Actions, `Some` on a runner.
match ctx.repository() {
Some(repo) => println!("running for {repo}"),
None => println!("not in GitHub Actions"),
}Implementations§
Source§impl Context
impl Context
Sourcepub fn new() -> Self
pub fn new() -> Self
Construct a context handle.
§Examples
let ctx = actions_rs::Context::new();
let _ = ctx.sha(); // each accessor is a fresh env readExamples found in repository?
13fn main() {
14 log::info(format!(
15 "in GitHub Actions: {} | CI: {} | step-debug: {}",
16 env::is_github_actions(),
17 env::is_ci(),
18 log::is_debug()
19 ));
20
21 let ctx = actions_rs::Context::new();
22 log::info(format!(
23 "repo={:?} ref={:?} sha={:?}",
24 ctx.repository(),
25 ctx.ref_name(),
26 ctx.sha()
27 ));
28
29 // Located annotation with a line range — should print:
30 // ::warning title=demo,file=src/lib.rs,line=10,endLine=12::heads up
31 Annotation::new()
32 .file("src/lib.rs")
33 .line(10)
34 .end_line(12)
35 .title("demo")
36 .warning("heads up: this span looks suspicious");
37
38 // Escaping check: newline in data, colon/comma in a property.
39 Annotation::new()
40 .title("type: mismatch, really")
41 .error("line one\nline two");
42
43 let total = log::group("expensive step", || {
44 log::info("...working...");
45 2 + 2
46 });
47 log::info(format!("group returned {total}"));
48
49 actions_rs::warning!("formatted macro: {} items left", 7);
50
51 output::set_output("answer", 42).expect("set_output");
52 match output::export_var("DEMO_FLAG", true) {
53 Ok(()) => {}
54 Err(actions_rs::Error::UnavailableFileCommand {
55 var: "GITHUB_ENV", ..
56 }) => {
57 log::info("GITHUB_ENV unset; skipping export_var in local demo");
58 }
59 Err(err) => panic!("export_var: {err}"),
60 }
61
62 let mut summary = Summary::new();
63 summary
64 .heading("Demo Report", 2)
65 .raw("Built by the `demo` example.", true)
66 .table([
67 vec![Cell::header("Check"), Cell::header("Result")],
68 vec![Cell::new("clippy"), Cell::new("pass")],
69 vec![Cell::new("tests"), Cell::new("36 pass")],
70 ])
71 .code_block("cargo test", Some("sh"));
72 summary.write().expect("write summary");
73 log::info("summary written (if GITHUB_STEP_SUMMARY was set)");
74}Sourcepub fn repository(&self) -> Option<String>
pub fn repository(&self) -> Option<String>
owner/repo, if set.
§Examples
let ctx = actions_rs::Context::new();
if let Some(repo) = ctx.repository() {
assert!(repo.contains('/'));
}Examples found in repository?
13fn main() {
14 log::info(format!(
15 "in GitHub Actions: {} | CI: {} | step-debug: {}",
16 env::is_github_actions(),
17 env::is_ci(),
18 log::is_debug()
19 ));
20
21 let ctx = actions_rs::Context::new();
22 log::info(format!(
23 "repo={:?} ref={:?} sha={:?}",
24 ctx.repository(),
25 ctx.ref_name(),
26 ctx.sha()
27 ));
28
29 // Located annotation with a line range — should print:
30 // ::warning title=demo,file=src/lib.rs,line=10,endLine=12::heads up
31 Annotation::new()
32 .file("src/lib.rs")
33 .line(10)
34 .end_line(12)
35 .title("demo")
36 .warning("heads up: this span looks suspicious");
37
38 // Escaping check: newline in data, colon/comma in a property.
39 Annotation::new()
40 .title("type: mismatch, really")
41 .error("line one\nline two");
42
43 let total = log::group("expensive step", || {
44 log::info("...working...");
45 2 + 2
46 });
47 log::info(format!("group returned {total}"));
48
49 actions_rs::warning!("formatted macro: {} items left", 7);
50
51 output::set_output("answer", 42).expect("set_output");
52 match output::export_var("DEMO_FLAG", true) {
53 Ok(()) => {}
54 Err(actions_rs::Error::UnavailableFileCommand {
55 var: "GITHUB_ENV", ..
56 }) => {
57 log::info("GITHUB_ENV unset; skipping export_var in local demo");
58 }
59 Err(err) => panic!("export_var: {err}"),
60 }
61
62 let mut summary = Summary::new();
63 summary
64 .heading("Demo Report", 2)
65 .raw("Built by the `demo` example.", true)
66 .table([
67 vec![Cell::header("Check"), Cell::header("Result")],
68 vec![Cell::new("clippy"), Cell::new("pass")],
69 vec![Cell::new("tests"), Cell::new("36 pass")],
70 ])
71 .code_block("cargo test", Some("sh"));
72 summary.write().expect("write summary");
73 log::info("summary written (if GITHUB_STEP_SUMMARY was set)");
74}Sourcepub fn repo_parts(&self) -> Option<(String, String)>
pub fn repo_parts(&self) -> Option<(String, String)>
(owner, repo) split from Context::repository.
§Examples
let ctx = actions_rs::Context::new();
if let Some((owner, repo)) = ctx.repo_parts() {
assert!(!owner.is_empty() && !repo.is_empty());
}Sourcepub fn repository_owner(&self) -> Option<String>
pub fn repository_owner(&self) -> Option<String>
Repository owner login.
§Examples
if let Some(owner) = actions_rs::Context::new().repository_owner() {
assert!(!owner.is_empty());
}Sourcepub fn sha(&self) -> Option<String>
pub fn sha(&self) -> Option<String>
Commit SHA that triggered the run.
§Examples
if let Some(sha) = actions_rs::Context::new().sha() {
assert!(!sha.is_empty());
}Examples found in repository?
13fn main() {
14 log::info(format!(
15 "in GitHub Actions: {} | CI: {} | step-debug: {}",
16 env::is_github_actions(),
17 env::is_ci(),
18 log::is_debug()
19 ));
20
21 let ctx = actions_rs::Context::new();
22 log::info(format!(
23 "repo={:?} ref={:?} sha={:?}",
24 ctx.repository(),
25 ctx.ref_name(),
26 ctx.sha()
27 ));
28
29 // Located annotation with a line range — should print:
30 // ::warning title=demo,file=src/lib.rs,line=10,endLine=12::heads up
31 Annotation::new()
32 .file("src/lib.rs")
33 .line(10)
34 .end_line(12)
35 .title("demo")
36 .warning("heads up: this span looks suspicious");
37
38 // Escaping check: newline in data, colon/comma in a property.
39 Annotation::new()
40 .title("type: mismatch, really")
41 .error("line one\nline two");
42
43 let total = log::group("expensive step", || {
44 log::info("...working...");
45 2 + 2
46 });
47 log::info(format!("group returned {total}"));
48
49 actions_rs::warning!("formatted macro: {} items left", 7);
50
51 output::set_output("answer", 42).expect("set_output");
52 match output::export_var("DEMO_FLAG", true) {
53 Ok(()) => {}
54 Err(actions_rs::Error::UnavailableFileCommand {
55 var: "GITHUB_ENV", ..
56 }) => {
57 log::info("GITHUB_ENV unset; skipping export_var in local demo");
58 }
59 Err(err) => panic!("export_var: {err}"),
60 }
61
62 let mut summary = Summary::new();
63 summary
64 .heading("Demo Report", 2)
65 .raw("Built by the `demo` example.", true)
66 .table([
67 vec![Cell::header("Check"), Cell::header("Result")],
68 vec![Cell::new("clippy"), Cell::new("pass")],
69 vec![Cell::new("tests"), Cell::new("36 pass")],
70 ])
71 .code_block("cargo test", Some("sh"));
72 summary.write().expect("write summary");
73 log::info("summary written (if GITHUB_STEP_SUMMARY was set)");
74}Sourcepub fn git_ref(&self) -> Option<String>
pub fn git_ref(&self) -> Option<String>
Full git ref, e.g. refs/heads/main.
§Examples
if let Some(r) = actions_rs::Context::new().git_ref() {
assert!(!r.is_empty());
}Sourcepub fn ref_name(&self) -> Option<String>
pub fn ref_name(&self) -> Option<String>
Short ref name, e.g. main.
§Examples
if let Some(name) = actions_rs::Context::new().ref_name() {
assert!(!name.is_empty());
}Examples found in repository?
13fn main() {
14 log::info(format!(
15 "in GitHub Actions: {} | CI: {} | step-debug: {}",
16 env::is_github_actions(),
17 env::is_ci(),
18 log::is_debug()
19 ));
20
21 let ctx = actions_rs::Context::new();
22 log::info(format!(
23 "repo={:?} ref={:?} sha={:?}",
24 ctx.repository(),
25 ctx.ref_name(),
26 ctx.sha()
27 ));
28
29 // Located annotation with a line range — should print:
30 // ::warning title=demo,file=src/lib.rs,line=10,endLine=12::heads up
31 Annotation::new()
32 .file("src/lib.rs")
33 .line(10)
34 .end_line(12)
35 .title("demo")
36 .warning("heads up: this span looks suspicious");
37
38 // Escaping check: newline in data, colon/comma in a property.
39 Annotation::new()
40 .title("type: mismatch, really")
41 .error("line one\nline two");
42
43 let total = log::group("expensive step", || {
44 log::info("...working...");
45 2 + 2
46 });
47 log::info(format!("group returned {total}"));
48
49 actions_rs::warning!("formatted macro: {} items left", 7);
50
51 output::set_output("answer", 42).expect("set_output");
52 match output::export_var("DEMO_FLAG", true) {
53 Ok(()) => {}
54 Err(actions_rs::Error::UnavailableFileCommand {
55 var: "GITHUB_ENV", ..
56 }) => {
57 log::info("GITHUB_ENV unset; skipping export_var in local demo");
58 }
59 Err(err) => panic!("export_var: {err}"),
60 }
61
62 let mut summary = Summary::new();
63 summary
64 .heading("Demo Report", 2)
65 .raw("Built by the `demo` example.", true)
66 .table([
67 vec![Cell::header("Check"), Cell::header("Result")],
68 vec![Cell::new("clippy"), Cell::new("pass")],
69 vec![Cell::new("tests"), Cell::new("36 pass")],
70 ])
71 .code_block("cargo test", Some("sh"));
72 summary.write().expect("write summary");
73 log::info("summary written (if GITHUB_STEP_SUMMARY was set)");
74}Sourcepub fn ref_type(&self) -> Option<String>
pub fn ref_type(&self) -> Option<String>
branch or tag.
§Examples
if let Some(t) = actions_rs::Context::new().ref_type() {
assert!(t == "branch" || t == "tag");
}Sourcepub fn head_ref(&self) -> Option<String>
pub fn head_ref(&self) -> Option<String>
PR head ref (empty/None outside pull requests).
§Examples
// `None` for `push` events; `Some(branch)` on a pull request.
let ctx = actions_rs::Context::new();
if let Some(head) = ctx.head_ref() {
assert!(!head.is_empty());
}Sourcepub fn base_ref(&self) -> Option<String>
pub fn base_ref(&self) -> Option<String>
PR base ref (empty/None outside pull requests).
§Examples
if let Some(base) = actions_rs::Context::new().base_ref() {
assert!(!base.is_empty()); // e.g. "main"
}Sourcepub fn event_name(&self) -> Option<String>
pub fn event_name(&self) -> Option<String>
Event name, e.g. push, pull_request.
§Examples
let ctx = actions_rs::Context::new();
if ctx.event_name().as_deref() == Some("pull_request") {
actions_rs::log::info("triggered by a PR");
}Sourcepub fn event_path(&self) -> Option<PathBuf>
pub fn event_path(&self) -> Option<PathBuf>
Path to the webhook payload JSON file.
§Examples
// The crate is serde-free, so you parse the JSON yourself if needed.
if let Some(path) = actions_rs::Context::new().event_path() {
let _payload = std::fs::read_to_string(path);
}Sourcepub fn workspace(&self) -> Option<PathBuf>
pub fn workspace(&self) -> Option<PathBuf>
Workspace directory (checked-out repo root).
§Examples
if let Some(ws) = actions_rs::Context::new().workspace() {
let _manifest = ws.join("Cargo.toml");
}Sourcepub fn workflow(&self) -> Option<String>
pub fn workflow(&self) -> Option<String>
Workflow name.
§Examples
if let Some(wf) = actions_rs::Context::new().workflow() {
assert!(!wf.is_empty());
}Sourcepub fn job(&self) -> Option<String>
pub fn job(&self) -> Option<String>
Current job id.
§Examples
if let Some(job) = actions_rs::Context::new().job() {
assert!(!job.is_empty()); // the `jobs:` map key, not its `name:`
}Sourcepub fn run_id(&self) -> Option<u64>
pub fn run_id(&self) -> Option<u64>
Unique numeric run id.
§Examples
if let Some(id) = actions_rs::Context::new().run_id() {
let _url = format!("https://github.com/o/r/actions/runs/{id}");
}Sourcepub fn run_number(&self) -> Option<u64>
pub fn run_number(&self) -> Option<u64>
Per-workflow incrementing run number.
§Examples
if let Some(n) = actions_rs::Context::new().run_number() {
let _ = n; // stable across re-runs, unlike `run_id`
}Sourcepub fn actor(&self) -> Option<String>
pub fn actor(&self) -> Option<String>
Login of the triggering user/app.
§Examples
if let Some(actor) = actions_rs::Context::new().actor() {
assert!(!actor.is_empty());
}Sourcepub fn server_url(&self) -> Option<String>
pub fn server_url(&self) -> Option<String>
Server URL (https://github.com or an Enterprise URL).
§Examples
if let Some(url) = actions_rs::Context::new().server_url() {
assert!(url.starts_with("http"));
}Sourcepub fn api_url(&self) -> Option<String>
pub fn api_url(&self) -> Option<String>
REST API base URL.
§Examples
if let Some(api) = actions_rs::Context::new().api_url() {
assert!(api.starts_with("http"));
}Sourcepub fn graphql_url(&self) -> Option<String>
pub fn graphql_url(&self) -> Option<String>
GraphQL API URL.
§Examples
if let Some(gql) = actions_rs::Context::new().graphql_url() {
assert!(gql.starts_with("http"));
}