Skip to content

Commit 016fb68

Browse files
invoke-workflow
0 parents  commit 016fb68

File tree

8 files changed

+187
-0
lines changed

8 files changed

+187
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.pytest_cache
2+
__pycache__
3+
.env
4+
env

Dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM python:3.10-alpine AS builder
2+
3+
WORKDIR /invoke-workflow
4+
5+
COPY ./requirements.txt .
6+
7+
RUN pip3 install -r ./requirements.txt -t .
8+
9+
FROM gcr.io/distroless/python3 as invoke-workflow
10+
11+
COPY --from=builder /invoke-workflow /invoke-workflow
12+
13+
WORKDIR /invoke-workflow
14+
15+
COPY . .
16+
17+
ENTRYPOINT ["python3"]
18+
CMD ["/invoke-workflow/main.py"]

README.md

Whitespace-only changes.

action.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: "Invoke Workflow"
2+
description: "When a workflow is configured to run on the workflow_dispatch event, you can run the workflow using this action"
3+
author: Singnet
4+
inputs:
5+
repo:
6+
description: "Repository name"
7+
required: true
8+
type: string
9+
workflow:
10+
description: "Workflow id"
11+
required: true
12+
type: string
13+
ref:
14+
description: "Git reference (branch or tag) to run the workflow on"
15+
required: false
16+
type: string
17+
default: "master"
18+
github-token:
19+
description: "Github access token"
20+
required: true
21+
type: string
22+
branding:
23+
icon: "bell"
24+
color: "red"
25+
runs:
26+
using: "docker"
27+
image: "Dockerfile"
28+
env:
29+
GITHUB_REPOSITORY: ${{ inputs.repo }}
30+
GITHUB_TOKEN: ${{ inputs.github-token }}
31+
GITHUB_WORKFLOW_ID: ${{ inputs.workflow }}
32+
GIT_REFERENCE: ${{ inputs.ref }}
33+
GITHUB_ORG: ${{ }}

docker-compose.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: "3.9"
2+
3+
services:
4+
invoke-workflow:
5+
container_name: invoke-workflow
6+
build: .
7+
env_file:
8+
- .env

github.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import requests
2+
import time
3+
4+
5+
class Auth:
6+
def __init__(self, token, org, repo) -> None:
7+
self._token = token
8+
self.org = org
9+
self.repo = repo
10+
11+
def get_authenticated_header(self):
12+
return {
13+
"Authorization": f"token {self._token}",
14+
"Accept": "application/vnd.github.v3+json",
15+
}
16+
17+
18+
class Workflow:
19+
def __init__(self, auth: Auth):
20+
self._auth = auth
21+
22+
def _get_dispatch_url(self, workflow_id: str):
23+
return f"https://api.github.com/repos/{self._auth.org}/{self._auth.repo}/actions/workflows/{workflow_id}/dispatches"
24+
25+
def _get_runs_url(self, workflow_id: str):
26+
return f"https://api.github.com/repos/{self._auth.org}/{self._auth.repo}/actions/workflows/{workflow_id}/runs"
27+
28+
def _get_run_url(self, run_id: str):
29+
return f"https://api.github.com/repos/{self._auth.org}/{self._auth.repo}/actions/runs/{run_id}"
30+
31+
def _dispatch_workflow(self, ref: str, workflow_id: str):
32+
url = self._get_dispatch_url(workflow_id)
33+
34+
data = {"ref": ref}
35+
36+
response = requests.post(
37+
url,
38+
headers=self._auth.get_authenticated_header(),
39+
json=data,
40+
)
41+
42+
if response.status_code == 204:
43+
print(
44+
f" Successfully started workflow with ID: {workflow_id} on the repository: {self._auth.repo}."
45+
)
46+
else:
47+
print(
48+
f"Failed to start workflow with ID: {workflow_id} on the repository: {self._auth.repo}."
49+
)
50+
print(response.text)
51+
response.raise_for_status()
52+
53+
def _get_latest_run_id(self, workflow_id: str):
54+
url = self._get_runs_url(workflow_id)
55+
56+
response = requests.get(url, headers=self._auth.get_authenticated_header())
57+
58+
if response.status_code == 200:
59+
runs = response.json()
60+
run_id = runs["workflow_runs"][0]["id"]
61+
print(
62+
f"Workflow run retrieved. Details:\n - Owner: {self._auth.org}\n - Repository: {self._auth.repo}\n - Workflow ID: {workflow_id}\n - Run ID: {run_id}"
63+
)
64+
return run_id
65+
else:
66+
print("Failed to retrieve workflow run ID.")
67+
print(response.text)
68+
response.raise_for_status()
69+
70+
def _wait_for_completion(self, run_id: str, interval: int = 30):
71+
while True:
72+
response = requests.get(
73+
self._get_run_url(run_id),
74+
headers=self._auth.get_authenticated_header(),
75+
)
76+
if response.status_code == 200:
77+
run = response.json()
78+
print(f"Current status of workflow run ID {run_id}: {run['status']}")
79+
if run["status"] == "completed":
80+
conclusion = run["conclusion"]
81+
print(
82+
f"Workflow run with ID {run_id} has completed with conclusion: {conclusion}"
83+
)
84+
return run["status"]
85+
else:
86+
time.sleep(interval)
87+
else:
88+
print("Failed to retrieve workflow run status.")
89+
print(response.text)
90+
response.raise_for_status()
91+
92+
def invoke(self, ref: str, workflow_id: str):
93+
self._dispatch_workflow(ref, workflow_id)
94+
time.sleep(10)
95+
run_id = self._get_latest_run_id(workflow_id)
96+
return self._wait_for_completion(run_id)

main.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
import github
3+
4+
5+
def main():
6+
organization = os.getenv("GITHUB_ORG")
7+
repository = os.getenv("GITHUB_REPOSITORY")
8+
token = os.getenv("GITHUB_TOKEN")
9+
workflow_id = os.getenv("GITHUB_WORKFLOW_ID")
10+
git_reference = os.getenv("GIT_REFERENCE")
11+
12+
auth = github.Auth(
13+
token,
14+
organization,
15+
repository,
16+
)
17+
18+
workflow = github.Workflow(auth)
19+
20+
workflow.invoke(
21+
ref=git_reference,
22+
workflow_id=workflow_id,
23+
)
24+
25+
26+
if __name__ == "__main__":
27+
main()

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requests==2.32.3

0 commit comments

Comments
 (0)