# 📌 gha-pinner
## Table of Contents
- [🤔 Why should you pin your GitHub Actions?](#-why-should-you-pin-your-github-actions)
- [🚀 What does `gha-pinner` do?](#-what-does-gha-pinner-do)
- [📦 Installation](#-installation)
- [🛠️ Usage](#️-usage)
## 🤔 Why should you pin your GitHub Actions?
Ever felt a bit of a thrill-seeker using `actions/checkout@v3` or even `actions/checkout@main` in your workflows? While convenient, using floating references like tags, branches, or the `latest` tag means you're living on the edge.
Pinning your GitHub Actions to a specific commit SHA is your seatbelt for this ride. Here's why it's a non-negotiable security best practice:
- **🔐 Rock-Solid Immutability**: A commit SHA is a unique, unchangeable fingerprint for a specific version of the code. No surprises. You can be absolutely certain about the code executing in your workflow.
- **🛡️ Dodge Malicious Updates**: Tags (like `v3`), branches (like `main`), and even the `latest` keyword are mutable pointers. The repository owner can move them to a different commit, potentially slipping malicious code into your workflow without you ever knowing. Pinning to a SHA is like saying, "I'll have *this* exact version, and nothing else, thank you."
- **✅ Crystal-Clear Verifiability**: A pinned SHA lets you put on your detective hat. You can browse the repository at that exact commit, inspect the code, and confirm it's safe and sound.
## 🚀 What does `gha-pinner` do?
`gha-pinner` is your friendly neighborhood GitHub Actions detective. It's a simple command-line tool that does the hard work of pinning your actions for you.
Given a GitHub Action in the format `owner/repo@ref` (where `ref` can be a branch, tag, or even `latest`), `gha-pinner` will:
1. **🔎 Track Down the `ref`**: It sleuths out the provided `ref` and resolves it to a specific, full-length commit SHA.
2. **📍 Serve the Pinned Version**: It then hands you back the action, neatly pinned to that commit SHA.
For example, if you provide `actions/checkout@v3`, `gha-pinner` will resolve `v3` to the latest commit SHA in the `v3` tag and provide you with `actions/checkout@<commit_sha>`.
It can also update all actions in a workflow file or directory in place.
## 📦 Installation
You can install `gha-pinner` using pip:
```bash
pip install gha-pinner
```
## 🛠️ Usage
Ready to lock down your workflows? Here's how you can use `gha-pinner`.
**Pin a single action:**
To get the commit SHA for a specific action, use the `action` subcommand:
```bash
$ gha-pinner action actions/checkout@v3
Original: actions/checkout@v3
Pinned: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b
```
You can then use the pinned version in your GitHub Actions workflow file:
```yaml
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b
```
This ensures that you are always using the exact same version of the action, protecting you from any potential malicious updates.
**Pin an entire workflow file:**
To pin all actions in a workflow file, use the `file` subcommand:
```bash
$ gha-pinner file .github/workflows/ci.yml
✅ Successfully pinned actions in '.github/workflows/ci.yml'
```
This will update the file in place, pinning all actions to their latest commit SHA and adding a comment with the original version, so you don't forget where you came from. For example:
```yaml
- uses: actions/checkout@v3
```
will be updated to:
```yaml
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v3
```
**Pin all workflow files in a directory:**
To pin all actions in all workflow files within a directory (recursively), use the `dir` subcommand:
```bash
$ gha-pinner dir .github/workflows
✅ Successfully pinned actions in '.github/workflows/ci.yml'
✅ Successfully pinned actions in '.github/workflows/release.yml'
```
This will scan the specified directory recursively, finding all workflow files (`.yml` and `.yaml` files), and pin all actions in each file. It's a convenient way to secure all your workflows at once.
Raw data
{
"_id": null,
"home_page": "https://github.com/sapasapasapa/gha-pinner",
"name": "gha-pinner",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "github, actions, security, pin, sha",
"author": "Samuele Pasini",
"author_email": "sapa@bendingspoons.com",
"download_url": "https://files.pythonhosted.org/packages/b5/27/25f52628462d2c648fe1e7ea1ed1658c97ae40b5f23dd61b04bd3583a45e/gha_pinner-0.1.4.tar.gz",
"platform": null,
"description": "# \ud83d\udccc gha-pinner\n\n## Table of Contents\n\n- [\ud83e\udd14 Why should you pin your GitHub Actions?](#-why-should-you-pin-your-github-actions)\n- [\ud83d\ude80 What does `gha-pinner` do?](#-what-does-gha-pinner-do)\n- [\ud83d\udce6 Installation](#-installation)\n- [\ud83d\udee0\ufe0f Usage](#\ufe0f-usage)\n\n## \ud83e\udd14 Why should you pin your GitHub Actions?\n\nEver felt a bit of a thrill-seeker using `actions/checkout@v3` or even `actions/checkout@main` in your workflows? While convenient, using floating references like tags, branches, or the `latest` tag means you're living on the edge.\n\nPinning your GitHub Actions to a specific commit SHA is your seatbelt for this ride. Here's why it's a non-negotiable security best practice:\n\n- **\ud83d\udd10 Rock-Solid Immutability**: A commit SHA is a unique, unchangeable fingerprint for a specific version of the code. No surprises. You can be absolutely certain about the code executing in your workflow.\n- **\ud83d\udee1\ufe0f Dodge Malicious Updates**: Tags (like `v3`), branches (like `main`), and even the `latest` keyword are mutable pointers. The repository owner can move them to a different commit, potentially slipping malicious code into your workflow without you ever knowing. Pinning to a SHA is like saying, \"I'll have *this* exact version, and nothing else, thank you.\"\n- **\u2705 Crystal-Clear Verifiability**: A pinned SHA lets you put on your detective hat. You can browse the repository at that exact commit, inspect the code, and confirm it's safe and sound.\n\n## \ud83d\ude80 What does `gha-pinner` do?\n\n`gha-pinner` is your friendly neighborhood GitHub Actions detective. It's a simple command-line tool that does the hard work of pinning your actions for you.\n\nGiven a GitHub Action in the format `owner/repo@ref` (where `ref` can be a branch, tag, or even `latest`), `gha-pinner` will:\n\n1. **\ud83d\udd0e Track Down the `ref`**: It sleuths out the provided `ref` and resolves it to a specific, full-length commit SHA.\n2. **\ud83d\udccd Serve the Pinned Version**: It then hands you back the action, neatly pinned to that commit SHA.\n\nFor example, if you provide `actions/checkout@v3`, `gha-pinner` will resolve `v3` to the latest commit SHA in the `v3` tag and provide you with `actions/checkout@<commit_sha>`.\n\nIt can also update all actions in a workflow file or directory in place.\n\n## \ud83d\udce6 Installation\n\nYou can install `gha-pinner` using pip:\n\n```bash\npip install gha-pinner\n```\n\n## \ud83d\udee0\ufe0f Usage\n\nReady to lock down your workflows? Here's how you can use `gha-pinner`.\n\n**Pin a single action:**\n\nTo get the commit SHA for a specific action, use the `action` subcommand:\n\n```bash\n$ gha-pinner action actions/checkout@v3\nOriginal: actions/checkout@v3\nPinned: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b\n```\n\nYou can then use the pinned version in your GitHub Actions workflow file:\n\n```yaml\n- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b\n```\n\nThis ensures that you are always using the exact same version of the action, protecting you from any potential malicious updates.\n\n**Pin an entire workflow file:**\n\nTo pin all actions in a workflow file, use the `file` subcommand:\n\n```bash\n$ gha-pinner file .github/workflows/ci.yml\n\u2705 Successfully pinned actions in '.github/workflows/ci.yml'\n```\n\nThis will update the file in place, pinning all actions to their latest commit SHA and adding a comment with the original version, so you don't forget where you came from. For example:\n\n```yaml\n- uses: actions/checkout@v3\n```\n\nwill be updated to:\n\n```yaml\n- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v3\n```\n\n**Pin all workflow files in a directory:**\n\nTo pin all actions in all workflow files within a directory (recursively), use the `dir` subcommand:\n\n```bash\n$ gha-pinner dir .github/workflows\n\u2705 Successfully pinned actions in '.github/workflows/ci.yml'\n\u2705 Successfully pinned actions in '.github/workflows/release.yml'\n```\n\nThis will scan the specified directory recursively, finding all workflow files (`.yml` and `.yaml` files), and pin all actions in each file. It's a convenient way to secure all your workflows at once.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Pin GitHub Actions to specific commit SHAs for improved security",
"version": "0.1.4",
"project_urls": {
"Homepage": "https://github.com/sapasapasapa/gha-pinner",
"Repository": "https://github.com/sapasapasapa/gha-pinner"
},
"split_keywords": [
"github",
" actions",
" security",
" pin",
" sha"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "25586d2f13b266930840e304d7218ff8b42870b270c13554253c777af5ead573",
"md5": "058ea6358bab4ae5564c945b5726379b",
"sha256": "ed376692fd89dad6bd5dc038db14266d49bf89eb291c1846e883b050729cae60"
},
"downloads": -1,
"filename": "gha_pinner-0.1.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "058ea6358bab4ae5564c945b5726379b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 13250,
"upload_time": "2025-07-25T12:19:51",
"upload_time_iso_8601": "2025-07-25T12:19:51.088225Z",
"url": "https://files.pythonhosted.org/packages/25/58/6d2f13b266930840e304d7218ff8b42870b270c13554253c777af5ead573/gha_pinner-0.1.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b52725f52628462d2c648fe1e7ea1ed1658c97ae40b5f23dd61b04bd3583a45e",
"md5": "33f4a05fce5d839c45475e40feba2582",
"sha256": "116f7e347ad55db1edcdb83ace12b6c880efb05a66a64737445d971a7a763772"
},
"downloads": -1,
"filename": "gha_pinner-0.1.4.tar.gz",
"has_sig": false,
"md5_digest": "33f4a05fce5d839c45475e40feba2582",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 11607,
"upload_time": "2025-07-25T12:19:52",
"upload_time_iso_8601": "2025-07-25T12:19:52.154109Z",
"url": "https://files.pythonhosted.org/packages/b5/27/25f52628462d2c648fe1e7ea1ed1658c97ae40b5f23dd61b04bd3583a45e/gha_pinner-0.1.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-25 12:19:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "sapasapasapa",
"github_project": "gha-pinner",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "gha-pinner"
}