or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdgit-operations.mdindex.mdissues-pull-requests.mdrepository-management.mdsearch-discovery.mduser-organization-management.mdworkflows-actions.md

workflows-actions.mddocs/

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

```