0
# Workflows and Actions
1
2
GitHub Actions workflow management, workflow runs, jobs, artifacts, and self-hosted runners. Supports automation and CI/CD pipeline integration with comprehensive access to GitHub Actions functionality.
3
4
## Capabilities
5
6
### Workflow Management
7
8
Access and manage GitHub Actions workflows within repositories.
9
10
```python { .api }
11
class Repository:
12
def get_workflows(self):
13
"""
14
Get repository workflows.
15
16
Returns:
17
PaginatedList[Workflow]: List of workflows
18
"""
19
20
def get_workflow(self, id_or_name: Union[int, str]):
21
"""
22
Get a specific workflow by ID or filename.
23
24
Args:
25
id_or_name (Union[int, str]): Workflow ID or filename
26
27
Returns:
28
Workflow: Workflow object
29
"""
30
31
class Workflow:
32
@property
33
def id(self) -> int: ...
34
@property
35
def name(self) -> str: ...
36
@property
37
def path(self) -> str: ...
38
@property
39
def state(self) -> str: ... # "active", "deleted", "disabled_fork", "disabled_inactivity", "disabled_manually"
40
@property
41
def created_at(self) -> datetime: ...
42
@property
43
def updated_at(self) -> datetime: ...
44
@property
45
def url(self) -> str: ...
46
@property
47
def html_url(self) -> str: ...
48
@property
49
def badge_url(self) -> str: ...
50
51
def create_dispatch(self, ref: str, inputs: dict = None):
52
"""
53
Trigger a workflow dispatch event.
54
55
Args:
56
ref (str): Git reference (branch or tag) to run workflow on
57
inputs (dict, optional): Input parameters for the workflow
58
"""
59
60
def get_runs(
61
self,
62
actor: str = None,
63
branch: str = None,
64
event: str = None,
65
status: str = None,
66
created: str = None,
67
exclude_pull_requests: bool = None
68
):
69
"""
70
Get workflow runs.
71
72
Args:
73
actor (str, optional): Filter by actor username
74
branch (str, optional): Filter by branch name
75
event (str, optional): Filter by event type
76
status (str, optional): Filter by status ("completed", "action_required", "cancelled", "failure", "neutral", "skipped", "stale", "success", "timed_out", "in_progress", "queued", "requested", "waiting", "pending")
77
created (str, optional): Filter by creation date (ISO 8601)
78
exclude_pull_requests (bool, optional): Exclude pull request runs
79
80
Returns:
81
PaginatedList[WorkflowRun]: List of workflow runs
82
"""
83
84
def enable(self):
85
"""Enable the workflow."""
86
87
def disable(self):
88
"""Disable the workflow."""
89
```
90
91
### Workflow Run Management
92
93
Manage individual workflow run instances, including cancellation, re-running, and accessing logs.
94
95
```python { .api }
96
class Repository:
97
def get_workflow_runs(
98
self,
99
actor: str = None,
100
branch: str = None,
101
event: str = None,
102
status: str = None,
103
created: str = None,
104
exclude_pull_requests: bool = None
105
):
106
"""
107
Get all workflow runs for the repository.
108
109
Args:
110
actor (str, optional): Filter by actor username
111
branch (str, optional): Filter by branch name
112
event (str, optional): Filter by event type
113
status (str, optional): Filter by status
114
created (str, optional): Filter by creation date
115
exclude_pull_requests (bool, optional): Exclude PR runs
116
117
Returns:
118
PaginatedList[WorkflowRun]: List of workflow runs
119
"""
120
121
def get_workflow_run(self, id: int):
122
"""
123
Get a specific workflow run.
124
125
Args:
126
id (int): Workflow run ID
127
128
Returns:
129
WorkflowRun: Workflow run object
130
"""
131
132
class WorkflowRun:
133
@property
134
def id(self) -> int: ...
135
@property
136
def name(self) -> str: ...
137
@property
138
def head_branch(self) -> str: ...
139
@property
140
def head_sha(self) -> str: ...
141
@property
142
def path(self) -> str: ...
143
@property
144
def display_title(self) -> str: ...
145
@property
146
def run_number(self) -> int: ...
147
@property
148
def event(self) -> str: ...
149
@property
150
def status(self) -> str: ... # "queued", "in_progress", "completed", "waiting"
151
@property
152
def conclusion(self) -> str: ... # "success", "failure", "neutral", "cancelled", "skipped", "timed_out", "action_required"
153
@property
154
def workflow_id(self) -> int: ...
155
@property
156
def check_suite_id(self) -> int: ...
157
@property
158
def check_suite_node_id(self) -> str: ...
159
@property
160
def url(self) -> str: ...
161
@property
162
def html_url(self) -> str: ...
163
@property
164
def pull_requests(self) -> list: ...
165
@property
166
def created_at(self) -> datetime: ...
167
@property
168
def updated_at(self) -> datetime: ...
169
@property
170
def actor(self) -> NamedUser: ...
171
@property
172
def run_attempt(self) -> int: ...
173
@property
174
def referenced_workflows(self) -> list: ...
175
@property
176
def run_started_at(self) -> datetime: ...
177
@property
178
def triggering_actor(self) -> NamedUser: ...
179
@property
180
def jobs_url(self) -> str: ...
181
@property
182
def logs_url(self) -> str: ...
183
@property
184
def check_suite_url(self) -> str: ...
185
@property
186
def artifacts_url(self) -> str: ...
187
@property
188
def cancel_url(self) -> str: ...
189
@property
190
def rerun_url(self) -> str: ...
191
@property
192
def previous_attempt_url(self) -> str: ...
193
@property
194
def workflow_url(self) -> str: ...
195
@property
196
def head_commit(self) -> dict: ...
197
@property
198
def repository(self) -> Repository: ...
199
@property
200
def head_repository(self) -> Repository: ...
201
202
def cancel(self):
203
"""Cancel the workflow run."""
204
205
def rerun(self, enable_debug_logging: bool = None):
206
"""
207
Re-run the workflow run.
208
209
Args:
210
enable_debug_logging (bool, optional): Enable debug logging for re-run
211
"""
212
213
def rerun_failed_jobs(self, enable_debug_logging: bool = None):
214
"""
215
Re-run failed jobs in the workflow run.
216
217
Args:
218
enable_debug_logging (bool, optional): Enable debug logging for re-run
219
"""
220
221
def get_jobs(self, filter: str = None):
222
"""
223
Get jobs for the workflow run.
224
225
Args:
226
filter (str, optional): Filter jobs ("latest", "all")
227
228
Returns:
229
PaginatedList[WorkflowJob]: List of jobs
230
"""
231
232
def get_artifacts(self, name: str = None):
233
"""
234
Get artifacts for the workflow run.
235
236
Args:
237
name (str, optional): Filter by artifact name
238
239
Returns:
240
PaginatedList[Artifact]: List of artifacts
241
"""
242
243
def delete(self):
244
"""Delete the workflow run."""
245
246
def get_logs(self):
247
"""
248
Get logs archive URL for the workflow run.
249
250
Returns:
251
str: URL to download logs archive
252
"""
253
254
def delete_logs(self):
255
"""Delete logs for the workflow run."""
256
257
def get_pending_deployments(self):
258
"""
259
Get pending deployments for the workflow run.
260
261
Returns:
262
list: List of pending deployments
263
"""
264
265
def approve_pending_deployments(self, environment_ids: list, state: str, comment: str):
266
"""
267
Approve or reject pending deployments.
268
269
Args:
270
environment_ids (list): List of environment IDs
271
state (str): Approval state ("approved", "rejected")
272
comment (str): Approval comment
273
"""
274
```
275
276
### Job Management
277
278
Access individual job information within workflow runs.
279
280
```python { .api }
281
class WorkflowJob:
282
@property
283
def id(self) -> int: ...
284
@property
285
def run_id(self) -> int: ...
286
@property
287
def workflow_name(self) -> str: ...
288
@property
289
def head_branch(self) -> str: ...
290
@property
291
def run_url(self) -> str: ...
292
@property
293
def run_attempt(self) -> int: ...
294
@property
295
def node_id(self) -> str: ...
296
@property
297
def head_sha(self) -> str: ...
298
@property
299
def url(self) -> str: ...
300
@property
301
def html_url(self) -> str: ...
302
@property
303
def status(self) -> str: ... # "queued", "in_progress", "completed", "waiting"
304
@property
305
def conclusion(self) -> str: ... # "success", "failure", "neutral", "cancelled", "skipped", "timed_out", "action_required"
306
@property
307
def created_at(self) -> datetime: ...
308
@property
309
def started_at(self) -> datetime: ...
310
@property
311
def completed_at(self) -> datetime: ...
312
@property
313
def name(self) -> str: ...
314
@property
315
def steps(self) -> list: ... # List of WorkflowStep objects
316
@property
317
def check_run_url(self) -> str: ...
318
@property
319
def labels(self) -> list: ...
320
@property
321
def runner_id(self) -> int: ...
322
@property
323
def runner_name(self) -> str: ...
324
@property
325
def runner_group_id(self) -> int: ...
326
@property
327
def runner_group_name(self) -> str: ...
328
329
def get_logs(self):
330
"""
331
Get logs for the job.
332
333
Returns:
334
str: Job logs content
335
"""
336
337
class WorkflowStep:
338
@property
339
def name(self) -> str: ...
340
@property
341
def status(self) -> str: ...
342
@property
343
def conclusion(self) -> str: ...
344
@property
345
def number(self) -> int: ...
346
@property
347
def started_at(self) -> datetime: ...
348
@property
349
def completed_at(self) -> datetime: ...
350
```
351
352
### Artifact Management
353
354
Handle workflow artifacts for storing and retrieving build outputs.
355
356
```python { .api }
357
class Repository:
358
def get_artifacts(self, name: str = None):
359
"""
360
Get repository artifacts.
361
362
Args:
363
name (str, optional): Filter by artifact name
364
365
Returns:
366
PaginatedList[Artifact]: List of artifacts
367
"""
368
369
def get_artifact(self, artifact_id: int):
370
"""
371
Get a specific artifact.
372
373
Args:
374
artifact_id (int): Artifact ID
375
376
Returns:
377
Artifact: Artifact object
378
"""
379
380
class Artifact:
381
@property
382
def id(self) -> int: ...
383
@property
384
def node_id(self) -> str: ...
385
@property
386
def name(self) -> str: ...
387
@property
388
def size_in_bytes(self) -> int: ...
389
@property
390
def url(self) -> str: ...
391
@property
392
def archive_download_url(self) -> str: ...
393
@property
394
def expired(self) -> bool: ...
395
@property
396
def created_at(self) -> datetime: ...
397
@property
398
def expires_at(self) -> datetime: ...
399
@property
400
def updated_at(self) -> datetime: ...
401
@property
402
def workflow_run(self) -> dict: ...
403
404
def delete(self):
405
"""Delete the artifact."""
406
407
def download_url(self):
408
"""
409
Get download URL for the artifact.
410
411
Returns:
412
str: Download URL
413
"""
414
```
415
416
### Self-Hosted Runners
417
418
Manage self-hosted runners for organizations and repositories.
419
420
```python { .api }
421
class Repository:
422
def get_self_hosted_runners(self, name: str = None):
423
"""
424
Get self-hosted runners for the repository.
425
426
Args:
427
name (str, optional): Filter by runner name
428
429
Returns:
430
PaginatedList[SelfHostedActionsRunner]: List of runners
431
"""
432
433
def get_self_hosted_runner(self, runner_id: int):
434
"""
435
Get a specific self-hosted runner.
436
437
Args:
438
runner_id (int): Runner ID
439
440
Returns:
441
SelfHostedActionsRunner: Runner object
442
"""
443
444
def create_runner_registration_token(self):
445
"""
446
Create a registration token for adding a self-hosted runner.
447
448
Returns:
449
dict: Registration token information
450
"""
451
452
def create_runner_removal_token(self):
453
"""
454
Create a removal token for removing a self-hosted runner.
455
456
Returns:
457
dict: Removal token information
458
"""
459
460
def remove_self_hosted_runner(self, runner_id: int):
461
"""
462
Remove a self-hosted runner.
463
464
Args:
465
runner_id (int): Runner ID
466
"""
467
468
class Organization:
469
def get_self_hosted_runners(self, name: str = None):
470
"""
471
Get self-hosted runners for the organization.
472
473
Args:
474
name (str, optional): Filter by runner name
475
476
Returns:
477
PaginatedList[SelfHostedActionsRunner]: List of runners
478
"""
479
480
def get_self_hosted_runner(self, runner_id: int):
481
"""
482
Get a specific self-hosted runner.
483
484
Args:
485
runner_id (int): Runner ID
486
487
Returns:
488
SelfHostedActionsRunner: Runner object
489
"""
490
491
def create_runner_registration_token(self):
492
"""
493
Create a registration token for adding a self-hosted runner.
494
495
Returns:
496
dict: Registration token information
497
"""
498
499
def create_runner_removal_token(self):
500
"""
501
Create a removal token for removing a self-hosted runner.
502
503
Returns:
504
dict: Removal token information
505
"""
506
507
def remove_self_hosted_runner(self, runner_id: int):
508
"""
509
Remove a self-hosted runner.
510
511
Args:
512
runner_id (int): Runner ID
513
"""
514
515
class SelfHostedActionsRunner:
516
@property
517
def id(self) -> int: ...
518
@property
519
def name(self) -> str: ...
520
@property
521
def os(self) -> str: ...
522
@property
523
def status(self) -> str: ... # "online", "offline"
524
@property
525
def busy(self) -> bool: ...
526
@property
527
def labels(self) -> list: ...
528
529
def remove(self):
530
"""Remove the runner."""
531
```
532
533
### Repository Secrets and Variables
534
535
Manage repository secrets and variables for Actions workflows.
536
537
```python { .api }
538
class Repository:
539
def get_secrets(self):
540
"""
541
Get repository secrets.
542
543
Returns:
544
PaginatedList[Secret]: List of secrets
545
"""
546
547
def get_secret(self, secret_name: str):
548
"""
549
Get a specific repository secret.
550
551
Args:
552
secret_name (str): Secret name
553
554
Returns:
555
Secret: Secret object
556
"""
557
558
def create_secret(self, secret_name: str, secret_value: str):
559
"""
560
Create or update a repository secret.
561
562
Args:
563
secret_name (str): Secret name
564
secret_value (str): Secret value
565
"""
566
567
def delete_secret(self, secret_name: str):
568
"""
569
Delete a repository secret.
570
571
Args:
572
secret_name (str): Secret name
573
"""
574
575
def get_variables(self):
576
"""
577
Get repository variables.
578
579
Returns:
580
PaginatedList[Variable]: List of variables
581
"""
582
583
def get_variable(self, variable_name: str):
584
"""
585
Get a specific repository variable.
586
587
Args:
588
variable_name (str): Variable name
589
590
Returns:
591
Variable: Variable object
592
"""
593
594
def create_variable(self, variable_name: str, value: str):
595
"""
596
Create or update a repository variable.
597
598
Args:
599
variable_name (str): Variable name
600
value (str): Variable value
601
"""
602
603
def delete_variable(self, variable_name: str):
604
"""
605
Delete a repository variable.
606
607
Args:
608
variable_name (str): Variable name
609
"""
610
611
class Secret:
612
@property
613
def name(self) -> str: ...
614
@property
615
def created_at(self) -> datetime: ...
616
@property
617
def updated_at(self) -> datetime: ...
618
619
class Variable:
620
@property
621
def name(self) -> str: ...
622
@property
623
def value(self) -> str: ...
624
@property
625
def created_at(self) -> datetime: ...
626
@property
627
def updated_at(self) -> datetime: ...
628
```
629
630
## Usage Examples
631
632
### Workflow Management
633
634
```python
635
from github import Github, Auth
636
637
g = Github(auth=Auth.Token("your_token"))
638
repo = g.get_repo("owner/repository")
639
640
# List all workflows
641
workflows = repo.get_workflows()
642
for workflow in workflows:
643
print(f"Workflow: {workflow.name} ({workflow.state})")
644
print(f"Path: {workflow.path}")
645
print(f"Badge: {workflow.badge_url}")
646
647
# Get specific workflow
648
workflow = repo.get_workflow("ci.yml")
649
print(f"Workflow ID: {workflow.id}")
650
651
# Trigger workflow dispatch
652
workflow.create_dispatch(
653
ref="main",
654
inputs={
655
"environment": "production",
656
"debug": "true"
657
}
658
)
659
print("Workflow dispatch triggered")
660
```
661
662
### Workflow Run Management
663
664
```python
665
# Get recent workflow runs
666
runs = repo.get_workflow_runs(status="completed")
667
for run in runs[:5]:
668
print(f"Run #{run.run_number}: {run.conclusion}")
669
print(f"Branch: {run.head_branch}")
670
print(f"Actor: {run.actor.login}")
671
print(f"Started: {run.run_started_at}")
672
673
# Get runs for specific workflow
674
ci_runs = workflow.get_runs(branch="main", status="completed")
675
for run in ci_runs[:3]:
676
print(f"CI Run: {run.conclusion} at {run.updated_at}")
677
678
# Cancel a running workflow
679
running_runs = repo.get_workflow_runs(status="in_progress")
680
if running_runs.totalCount > 0:
681
running_run = running_runs[0]
682
running_run.cancel()
683
print(f"Cancelled run #{running_run.run_number}")
684
685
# Re-run failed workflow
686
failed_runs = repo.get_workflow_runs(conclusion="failure")
687
if failed_runs.totalCount > 0:
688
failed_run = failed_runs[0]
689
failed_run.rerun_failed_jobs()
690
print(f"Re-running failed jobs for run #{failed_run.run_number}")
691
```
692
693
### Job and Step Details
694
695
```python
696
# Get jobs for a specific run
697
run = repo.get_workflow_run(12345)
698
jobs = run.get_jobs()
699
700
for job in jobs:
701
print(f"Job: {job.name}")
702
print(f"Status: {job.status}")
703
print(f"Conclusion: {job.conclusion}")
704
print(f"Runner: {job.runner_name}")
705
706
# Get job steps
707
for step in job.steps:
708
print(f" Step: {step.name}")
709
print(f" Status: {step.status}")
710
print(f" Conclusion: {step.conclusion}")
711
712
# Get job logs
713
logs = job.get_logs()
714
print(f"Logs (first 200 chars): {logs[:200]}...")
715
```
716
717
### Artifact Management
718
719
```python
720
# List artifacts for repository
721
artifacts = repo.get_artifacts()
722
for artifact in artifacts:
723
print(f"Artifact: {artifact.name}")
724
print(f"Size: {artifact.size_in_bytes} bytes")
725
print(f"Expired: {artifact.expired}")
726
print(f"Created: {artifact.created_at}")
727
728
# Get artifacts for specific run
729
run_artifacts = run.get_artifacts()
730
for artifact in run_artifacts:
731
print(f"Run artifact: {artifact.name}")
732
733
# Get download URL (requires authentication)
734
download_url = artifact.download_url()
735
print(f"Download URL: {download_url}")
736
737
# Delete old artifacts
738
expired_artifacts = repo.get_artifacts()
739
for artifact in expired_artifacts:
740
if artifact.expired:
741
artifact.delete()
742
print(f"Deleted expired artifact: {artifact.name}")
743
```
744
745
### Self-Hosted Runner Management
746
747
```python
748
# List self-hosted runners
749
runners = repo.get_self_hosted_runners()
750
for runner in runners:
751
print(f"Runner: {runner.name}")
752
print(f"OS: {runner.os}")
753
print(f"Status: {runner.status}")
754
print(f"Busy: {runner.busy}")
755
print(f"Labels: {runner.labels}")
756
757
# Create registration token for new runner
758
token_info = repo.create_runner_registration_token()
759
print(f"Registration token: {token_info['token']}")
760
print(f"Expires at: {token_info['expires_at']}")
761
762
# Remove offline runners
763
for runner in runners:
764
if runner.status == "offline":
765
runner.remove()
766
print(f"Removed offline runner: {runner.name}")
767
```
768
769
### Secrets and Variables Management
770
771
```python
772
# List repository secrets
773
secrets = repo.get_secrets()
774
for secret in secrets:
775
print(f"Secret: {secret.name}")
776
print(f"Updated: {secret.updated_at}")
777
778
# Create/update secret
779
repo.create_secret("API_KEY", "secret_value_here")
780
print("Secret created/updated")
781
782
# List repository variables
783
variables = repo.get_variables()
784
for variable in variables:
785
print(f"Variable: {variable.name} = {variable.value}")
786
787
# Create/update variable
788
repo.create_variable("ENVIRONMENT", "production")
789
print("Variable created/updated")
790
791
# Delete old secrets
792
repo.delete_secret("OLD_API_KEY")
793
print("Old secret deleted")
794
```
795
796
### Organization-Level Actions Management
797
798
```python
799
# Organization runners
800
org = g.get_organization("myorg")
801
org_runners = org.get_self_hosted_runners()
802
803
for runner in org_runners:
804
print(f"Org runner: {runner.name} ({runner.status})")
805
806
# Organization secrets
807
org_secrets = org.get_secrets()
808
for secret in org_secrets:
809
print(f"Org secret: {secret.name}")
810
811
# Create organization-level secret
812
org.create_secret("ORG_API_KEY", "organization_secret_value")
813
print("Organization secret created")
814
```
815
816
### Monitoring Workflow Health
817
818
```python
819
from datetime import datetime, timedelta
820
821
# Get recent failed runs
822
recent_date = datetime.now() - timedelta(days=7)
823
recent_runs = repo.get_workflow_runs(
824
created=recent_date.isoformat(),
825
status="completed"
826
)
827
828
failed_count = 0
829
success_count = 0
830
831
for run in recent_runs:
832
if run.conclusion == "failure":
833
failed_count += 1
834
print(f"Failed run #{run.run_number}: {run.name}")
835
elif run.conclusion == "success":
836
success_count += 1
837
838
success_rate = success_count / (success_count + failed_count) * 100
839
print(f"Success rate in last 7 days: {success_rate:.2f}%")
840
841
# Find long-running jobs
842
for run in recent_runs[:10]:
843
jobs = run.get_jobs()
844
for job in jobs:
845
if job.started_at and job.completed_at:
846
duration = job.completed_at - job.started_at
847
if duration.total_seconds() > 1800: # 30 minutes
848
print(f"Long-running job: {job.name} took {duration}")
849
```