Repository: google/go-github
Pull request #3476 (2025-02-12 09:40:30)

Add helper to get `runID` from Custom Deployment Protection Rule Event
Added Helper Function with test to get the RunID from the DeploymentCallbackURL and convert it to an int64.

Fixes: #3473.

google-cla[bot]: Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this [failed invocation](https://github.com/google/go-github/pull/3476/checks?check_run_id=37083373567) of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/google/go-github/pull/3476?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
Attention: Patch coverage is `66.66667%` with `3 lines` in your changes missing coverage. Please review.
> Project coverage is 91.02%. Comparing base [(`77684a4`)](https://app.codecov.io/gh/google/go-github/commit/77684a471bb9e7a677c09991025db547bdf82407?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) to head [(`19449c0`)](https://app.codecov.io/gh/google/go-github/commit/19449c007ef677e4ca1c150ab969cbef15499c94?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).

| [Files with missing lines](https://app.codecov.io/gh/google/go-github/pull/3476?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Patch % | Lines |
|---|---|---|
| [github/github.go](https://app.codecov.io/gh/google/go-github/pull/3476?src=pr&el=tree&filepath=github%2Fgithub.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL2dpdGh1Yi5nbw==) | 66.66% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/google/go-github/pull/3476?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #3476      +/-   ##
==========================================
- Coverage   91.04%   91.02%   -0.02%     
==========================================
  Files         179      179              
  Lines       15551    15560       +9     
==========================================
+ Hits        14158    14164       +6     
- Misses       1221     1223       +2     
- Partials      172      173       +1     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/google/go-github/pull/3476?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).

pputman-clabs: Okay I made the requested changes, thanks for the feedback!  Let me know if there's anything else programming wise you think I should change and if not I'll start adding the documentation for it to the other method docs.
pputman-clabs: Made requested changes, and added a comment to the actions_workflow_runs.go methods that they can use this helper function to easily pull out the RunID

Patch:
diff --git a/github/actions_workflow_runs.go b/github/actions_workflow_runs.go
index dddc56d2..20b9cfcd 100644
--- a/github/actions_workflow_runs.go
+++ b/github/actions_workflow_runs.go
@@ -204,6 +204,7 @@ func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner,
 }
 
 // GetWorkflowRunByID gets a specific workflow run by ID.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run
 //
@@ -226,6 +227,7 @@ func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo str
 }
 
 // GetWorkflowRunAttempt gets a specific workflow run attempt.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-a-workflow-run-attempt
 //
@@ -252,6 +254,7 @@ func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo
 }
 
 // GetWorkflowRunAttemptLogs gets a redirect URL to download a plain text file of logs for a workflow run for attempt number.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve a workflow run ID from the DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-attempt-logs
 //
@@ -302,6 +305,7 @@ func (s *ActionsService) getWorkflowRunAttemptLogsWithRateLimit(ctx context.Cont
 }
 
 // RerunWorkflowByID re-runs a workflow by ID.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID a the DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-workflow
 //
@@ -318,6 +322,7 @@ func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo stri
 }
 
 // RerunFailedJobsByID re-runs all of the failed jobs and their dependent jobs in a workflow run by ID.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-failed-jobs-from-a-workflow-run
 //
@@ -335,6 +340,8 @@ func (s *ActionsService) RerunFailedJobsByID(ctx context.Context, owner, repo st
 
 // RerunJobByID re-runs a job and its dependent jobs in a workflow run by ID.
 //
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
+//
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#re-run-a-job-from-a-workflow-run
 //
 //meta:operation POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun
@@ -350,6 +357,7 @@ func (s *ActionsService) RerunJobByID(ctx context.Context, owner, repo string, j
 }
 
 // CancelWorkflowRunByID cancels a workflow run by ID.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#cancel-a-workflow-run
 //
@@ -366,6 +374,7 @@ func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo
 }
 
 // GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#download-workflow-run-logs
 //
@@ -416,6 +425,7 @@ func (s *ActionsService) getWorkflowRunLogsWithRateLimit(ctx context.Context, u
 }
 
 // DeleteWorkflowRun deletes a workflow run by ID.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-a-workflow-run
 //
@@ -432,6 +442,7 @@ func (s *ActionsService) DeleteWorkflowRun(ctx context.Context, owner, repo stri
 }
 
 // DeleteWorkflowRunLogs deletes all logs for a workflow run.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#delete-workflow-run-logs
 //
@@ -448,6 +459,7 @@ func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo
 }
 
 // GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-workflow-run-usage
 //
@@ -470,6 +482,7 @@ func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, rep
 }
 
 // GetPendingDeployments get all deployment environments for a workflow run that are waiting for protection rules to pass.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#get-pending-deployments-for-a-workflow-run
 //
@@ -492,6 +505,7 @@ func (s *ActionsService) GetPendingDeployments(ctx context.Context, owner, repo
 }
 
 // PendingDeployments approve or reject pending deployments that are waiting on approval by a required reviewer.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-pending-deployments-for-a-workflow-run
 //
@@ -514,6 +528,7 @@ func (s *ActionsService) PendingDeployments(ctx context.Context, owner, repo str
 }
 
 // ReviewCustomDeploymentProtectionRule approves or rejects custom deployment protection rules provided by a GitHub App for a workflow run.
+// You can use the helper function *DeploymentProtectionRuleEvent.GetRunID() to easily retrieve the workflow run ID from a DeploymentProtectionRuleEvent.
 //
 // GitHub API docs: https://docs.github.com/rest/actions/workflow-runs#review-custom-deployment-protection-rules-for-a-workflow-run
 //
diff --git a/github/github.go b/github/github.go
index b7d22123..47bcf08f 100644
--- a/github/github.go
+++ b/github/github.go
@@ -19,6 +19,7 @@ import (
 	"net/http"
 	"net/url"
 	"reflect"
+	"regexp"
 	"strconv"
 	"strings"
 	"sync"
@@ -1770,3 +1771,18 @@ type roundTripperFunc func(*http.Request) (*http.Response, error)
 func (fn roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
 	return fn(r)
 }
+
+var runIDFromURLRE = regexp.MustCompile(`^repos/.*/actions/runs/(\d+)/deployment_protection_rule$`)
+
+// GetRunID is a Helper Function used to extract the workflow RunID from the *DeploymentProtectionRuleEvent.DeploymentCallBackURL.
+func (e *DeploymentProtectionRuleEvent) GetRunID() (int64, error) {
+	match := runIDFromURLRE.FindStringSubmatch(*e.DeploymentCallbackURL)
+	if len(match) != 2 {
+		return -1, errors.New("no match")
+	}
+	runID, err := strconv.ParseInt(match[1], 10, 64)
+	if err != nil {
+		return -1, err
+	}
+	return runID, nil
+}


Test patch:
diff --git a/github/github_test.go b/github/github_test.go
index b402f098..683012ad 100644
--- a/github/github_test.go
+++ b/github/github_test.go
@@ -3101,3 +3101,31 @@ func TestPtr(t *testing.T) {
 	equal(t, int64(-10), *Ptr(int64(-10)))
 	equal(t, "str", *Ptr("str"))
 }
+
+func TestDeploymentProtectionRuleEvent_GetRunID(t *testing.T) {
+	t.Parallel()
+
+	var want int64 = 123456789
+	url := "repos/dummy-org/dummy-repo/actions/runs/123456789/deployment_protection_rule"
+
+	e := DeploymentProtectionRuleEvent{
+		DeploymentCallbackURL: &url,
+	}
+
+	got, _ := e.GetRunID()
+	if got != want {
+		t.Errorf("want %#v, got %#v", want, got)
+	}
+
+	want = -1
+	url = "repos/dummy-org/dummy-repo/actions/runs/abc123/deployment_protection_rule"
+
+	got, err := e.GetRunID()
+	if err == nil {
+		t.Errorf("Expected error to be returned")
+	}
+
+	if got != want {
+		t.Errorf("want %#v, got %#v", want, got)
+	}
+}