{"id":19581177,"url":"https://github.com/google-github-actions/github-workflow-job-to-pubsub","last_synced_at":"2025-08-13T01:20:08.038Z","repository":{"id":55431272,"uuid":"414730365","full_name":"google-github-actions/github-workflow-job-to-pubsub","owner":"google-github-actions","description":"Fulfills a GitHub workflow_job webhooks into a Pub/Sub queue.","archived":false,"fork":false,"pushed_at":"2025-03-13T01:44:12.000Z","size":53,"stargazers_count":12,"open_issues_count":1,"forks_count":8,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-27T09:35:27.062Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/google-github-actions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null}},"created_at":"2021-10-07T19:22:38.000Z","updated_at":"2025-04-20T17:06:13.000Z","dependencies_parsed_at":"2024-04-19T16:34:39.456Z","dependency_job_id":"8e47535a-1bb6-4fd7-ae1c-4c94958059b0","html_url":"https://github.com/google-github-actions/github-workflow-job-to-pubsub","commit_stats":null,"previous_names":["sethvargo/github-workflow-job-to-pubsub"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/google-github-actions/github-workflow-job-to-pubsub","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google-github-actions%2Fgithub-workflow-job-to-pubsub","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google-github-actions%2Fgithub-workflow-job-to-pubsub/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google-github-actions%2Fgithub-workflow-job-to-pubsub/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google-github-actions%2Fgithub-workflow-job-to-pubsub/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/google-github-actions","download_url":"https://codeload.github.com/google-github-actions/github-workflow-job-to-pubsub/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/google-github-actions%2Fgithub-workflow-job-to-pubsub/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270162477,"owners_count":24537827,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T07:33:47.035Z","updated_at":"2025-08-13T01:20:07.995Z","avatar_url":"https://github.com/google-github-actions.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Workflow Job to Pub/Sub\n\nThe GitHub Workflow Job to Pub/Sub is a small service that fulfills a GitHub\n[`workflow_job` webhook][workflow-job-webhook].\n\n-   When a job is queued, it inserts one message onto a Pub/Sub topic.\n\n-   When a job is finished, it acknowledges one message from a Pub/Sub\n    subscription.\n\nThis means that, at any time, the number of unacknowledged messages in the\nPub/Sub topic corresponds to the number of queued or active GitHub Actions jobs.\nYou can use this property as an indicator in an auto-scaling metric or a means\nto queue new ephemeral workers.\n\n**This is not an officially supported Google product, and it is not covered by a\nGoogle Cloud support contract. To report bugs or request features in a Google\nCloud product, please contact [Google Cloud\nsupport](https://cloud.google.com/support).**\n\n\n## Deployment\n\nThis deployment example uses Google Cloud and [Cloud Run][cloud-run] to deploy\nand manage the proxy.\n\n1.  Create or use an existing Google Cloud project:\n\n    ```sh\n    export PROJECT_ID=\"...\"\n    ```\n\n1.  Enable required APIs:\n\n    ```sh\n    gcloud services enable --project=\"${PROJECT_ID}\" \\\n      artifactregistry.googleapis.com \\\n      cloudbuild.googleapis.com \\\n      pubsub.googleapis.com \\\n      run.googleapis.com \\\n      secretmanager.googleapis.com\n    ```\n\n1.  Create a service account to run the receiver:\n\n    ```sh\n    gcloud iam service-accounts create \"gh-webhook-receiver\" \\\n      --description=\"GitHub webhook receiver\" \\\n      --project=\"${PROJECT_ID}\"\n    ```\n\n1.  Create a GitHub Webhook secret and store it in Google Secret Manager. This\n    secret can be any value.\n\n    ```sh\n    echo -n \"\u003cYOUR SECRET\u003e\" | gcloud secrets create \"gh-webhook-secret\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --data-file=-\n    ```\n\n    If you do not have a secret, you can randomly generate a secret using\n    `openssl`:\n\n    ```sh\n    openssl rand -base64 32\n    ```\n\n1.  Grant the service account permissions to access the secret:\n\n    ```sh\n    gcloud secrets add-iam-policy-binding \"gh-webhook-secret\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --role=\"roles/secretmanager.secretAccessor\" \\\n      --member=\"serviceAccount:gh-webhook-receiver@${PROJECT_ID}.iam.gserviceaccount.com\"\n    ```\n\n1.  Create a Pub/Sub topic:\n\n    ```sh\n    gcloud pubsub topics create \"gh-topic\" \\\n      --project=\"${PROJECT_ID}\"\n    ```\n\n1.  Grant the service account permissions to publish to the topic:\n\n    ```sh\n    gcloud pubsub topics add-iam-policy-binding \"gh-topic\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --role=\"roles/pubsub.publisher\" \\\n      --member=\"serviceAccount:gh-webhook-receiver@${PROJECT_ID}.iam.gserviceaccount.com\"\n    ```\n\n1.  Create a Pub/Sub subscription:\n\n    ```sh\n    gcloud pubsub subscriptions create \"gh-subscription\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --topic=\"gh-topic\" \\\n      --ack-deadline=\"10\" \\\n      --message-retention-duration=\"1800s\" \\\n      --expiration-period=\"never\" \\\n      --min-retry-delay=\"5s\" \\\n      --max-retry-delay=\"30s\"\n    ```\n\n1.  Grant the service account permissions to pull from the subscription:\n\n    ```sh\n    gcloud pubsub subscriptions add-iam-policy-binding \"gh-subscription\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --role=\"roles/pubsub.subscriber\" \\\n      --member=\"serviceAccount:gh-webhook-receiver@${PROJECT_ID}.iam.gserviceaccount.com\"\n    ```\n\n1.  Create a repository in Artifact Registry to store the container:\n\n    ```sh\n    gcloud artifacts repositories create \"gh-webhook-receiver\" \\\n      --project=\"${PROJECT_ID}\" \\\n      --repository-format=\"docker\" \\\n      --location=\"us\" \\\n      --description=\"GitHub webhook receiver\"\n    ```\n\n1.  Build and push the container:\n\n    ```sh\n    gcloud builds submit . \\\n      --project=\"${PROJECT_ID}\" \\\n      --tag=\"us-docker.pkg.dev/${PROJECT_ID}/gh-webhook-receiver/gh-webhook-receiver\"\n    ```\n\n1.  Deploy the service and attach the secret (see\n    [Configuration](#configuration) for more information on available options):\n\n    ```sh\n    gcloud beta run deploy \"gh-webhook-receiver\" \\\n      --quiet \\\n      --project=\"${PROJECT_ID}\" \\\n      --region=\"us-east1\" \\\n      --set-secrets=\"GITHUB_WEBHOOK_SECRET=gh-webhook-secret:1\" \\\n      --set-env-vars=\"PUBSUB_TOPIC_NAME=projects/${PROJECT_ID}/topics/gh-topic,PUBSUB_SUBSCRIPTION_NAME=projects/${PROJECT_ID}/subscriptions/gh-subscription\" \\\n      --image=\"us-docker.pkg.dev/${PROJECT_ID}/gh-webhook-receiver/gh-webhook-receiver\" \\\n      --service-account=\"gh-webhook-receiver@${PROJECT_ID}.iam.gserviceaccount.com\" \\\n      --allow-unauthenticated\n    ```\n\n    Take note of the URL. It is important to note that this is a\n    **publicly-accessible URL**.\n\n1.  Create an organization webhook on GitHub:\n\n    - **Payload URL:** URL for the Cloud Run service above.\n    - **Content type:** application/json\n    - **Secret:** value from above\n    - **Events:** select \"individual events\" and then choose **only** \"Workflow jobs\"\n\n\n## Configuration\n\n-   `GITHUB_WEBHOOK_SECRET` - this is the secret key to use for authenticating\n    the webhook's HMAC. This must match the value given to GitHub when\n    configuring the webhook. It is very important that you choose a high-entropy\n    secret, because your service must be publicly accessible.\n\n-   `PUBSUB_TOPIC_NAME` - this is the name of the topic on which to publish.\n    This must be the full topic name including the project (e.g.\n    `projects/my-project/topics/my-topic`).\n\n-   `PUBSUB_SUBSCRIPTION_NAME` - this is the name of the subscription on which\n    to pull and acknowledge. This must be the full subscription name including\n    the project (e.g. `projects/my-project/subscriptions/my-subscription`).\n\n\n## FAQ\n\n**Q: Why is Pub/Sub necessary? Why not just have the service create ephemeral runners or scale a VM pool directly?**\n\u003cbr\u003e\nA: GitHub has a [timeout of 10 seconds][webhook-timeout] for webhook responses,\nand strongly recommends asynchronous processing. Modifying an autoscaling group\nor spinning up a new virtual machine will almost always exceed this timeout.\n\n[workflow-job-webhook]: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job\n[webhook-timeout]: https://docs.github.com/en/rest/guides/best-practices-for-integrators#favor-asynchronous-work-over-synchronous\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle-github-actions%2Fgithub-workflow-job-to-pubsub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoogle-github-actions%2Fgithub-workflow-job-to-pubsub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoogle-github-actions%2Fgithub-workflow-job-to-pubsub/lists"}