{"id":31200550,"url":"https://github.com/azat-io/actions-up","last_synced_at":"2025-10-07T03:57:27.940Z","repository":{"id":311833811,"uuid":"1045247927","full_name":"azat-io/actions-up","owner":"azat-io","description":"🌊 Interactive CLI tool to update GitHub Actions to latest versions with SHA pinning","archived":false,"fork":false,"pushed_at":"2025-09-20T09:37:34.000Z","size":790,"stargazers_count":271,"open_issues_count":1,"forks_count":10,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-09-20T11:16:07.612Z","etag":null,"topics":["actions","cli","dependencies","github-actions","security","workflow"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/azat-io.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.config.json","contributing":"contributing.md","funding":null,"license":"license.md","code_of_conduct":".github/code_of_conduct.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-26T21:52:22.000Z","updated_at":"2025-09-20T09:37:39.000Z","dependencies_parsed_at":"2025-09-11T23:19:03.660Z","dependency_job_id":"adc94ec9-519b-4e3f-9c7d-e7836fba2bae","html_url":"https://github.com/azat-io/actions-up","commit_stats":null,"previous_names":["azat-io/actions-up"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/azat-io/actions-up","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azat-io%2Factions-up","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azat-io%2Factions-up/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azat-io%2Factions-up/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azat-io%2Factions-up/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/azat-io","download_url":"https://codeload.github.com/azat-io/actions-up/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/azat-io%2Factions-up/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278717450,"owners_count":26033542,"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-10-07T02:00:06.786Z","response_time":59,"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":["actions","cli","dependencies","github-actions","security","workflow"],"created_at":"2025-09-20T11:02:14.847Z","updated_at":"2025-10-07T03:57:27.922Z","avatar_url":"https://github.com/azat-io.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Utilities"],"sub_categories":["Project Tools"],"readme":"# Actions Up!\n\n\u003cimg\n  src=\"https://raw.githubusercontent.com/azat-io/actions-up/main/assets/logo.svg\"\n  alt=\"Actions Up logo\"\n  width=\"160\"\n  height=\"160\"\n  align=\"right\"\n/\u003e\n\n[![Version](https://img.shields.io/npm/v/actions-up.svg?color=fff\u0026labelColor=4493f8)](https://npmjs.com/package/actions-up)\n[![Code Coverage](https://img.shields.io/codecov/c/github/azat-io/actions-up.svg?color=fff\u0026labelColor=4493f8)](https://codecov.io/gh/azat-io/actions-up)\n[![GitHub License](https://img.shields.io/badge/license-MIT-232428.svg?color=fff\u0026labelColor=4493f8)](https://github.com/azat-io/actions-up/blob/main/license.md)\n\nActions Up scans your workflows and composite actions to discover every referenced GitHub Action, then checks for newer releases.\n\nInteractively upgrade and pin actions to exact commit SHAs for secure, reproducible CI and low-friction maintenance.\n\n## Features\n\n- **Auto-discovery**: Scans all workflows (`.github/workflows/*.yml`) and composite actions (`.github/actions/*/action.yml`)\n- **SHA pinning**: Updates actions to use commit SHA instead of tags for better security\n- **Batch Updates**: Update multiple actions at once\n- **Interactive Selection**: Choose which actions to update\n- **Breaking Changes Detection**: Warns about major version updates\n- **Fast \u0026 Efficient**: Optimized API usage with deduped lookups\n- **CI/CD Integration**: Use in GitHub Actions workflows for automated PR checks\n\n###\n\n\u003cbr\u003e\n\n\u003cpicture\u003e\n  \u003csource\n    srcset=\"https://raw.githubusercontent.com/azat-io/actions-up/main/assets/example-light.webp\"\n    media=\"(prefers-color-scheme: light)\"\n  /\u003e\n  \u003csource\n    srcset=\"https://raw.githubusercontent.com/azat-io/actions-up/main/assets/example-dark.webp\"\n    media=\"(prefers-color-scheme: dark)\"\n  /\u003e\n  \u003cimg\n    src=\"https://raw.githubusercontent.com/azat-io/actions-up/main/assets/example-light.webp\"\n    alt=\"Actions Up! interactive example\"\n    width=\"820\"\n  /\u003e\n\u003c/picture\u003e\n\n## Why\n\n### The Problem\n\nKeeping GitHub Actions updated is a critical but tedious task:\n\n- **Security Risk**: Using outdated actions with known vulnerabilities\n- **Manual Hell**: Checking dozens of actions across multiple workflows by hand\n- **Version Tags Are Mutable**: v1 or v2 tags can change without notice, breaking reproducibility\n- **Time Sink**: Hours spent on maintenance that could be used for actual development\n\n### The Solution\n\nActions Up transforms a painful manual process into a delightful experience:\n\n| Without Actions Up             | With Actions Up                  |\n| :----------------------------- | :------------------------------- |\n| Check each action manually     | Scan all workflows in seconds    |\n| Risk using vulnerable versions | SHA pinning for maximum security |\n| 30+ minutes per repository     | Under 1 minute total             |\n\n## Installation\n\nQuick use (no installation)\n\n```bash\nnpx actions-up\n```\n\nGlobal installation\n\n```bash\nnpm install -g actions-up\n```\n\nPer-project\n\n```bash\nnpm install --save-dev actions-up\n```\n\n## Usage\n\n### Interactive Mode (Default)\n\nRun in your repository root:\n\n```bash\nnpx actions-up\n```\n\nThis will:\n\n1. Scan all `.github/workflows/*.yml` and `.github/actions/*/action.yml` files\n2. Check for available updates\n3. Show an interactive list to select updates\n4. Apply selected updates with SHA pinning\n\n### Auto-Update Mode\n\nSkip all prompts and update everything:\n\n```bash\nnpx actions-up --yes\n# or\nnpx actions-up -y\n```\n\n### Dry Run Mode\n\nCheck for updates without making any changes:\n\n```bash\nnpx actions-up --dry-run\n```\n\n## GitHub Actions Integration\n\n### Automated PR Checks\n\nYou can integrate Actions Up into your CI/CD pipeline to automatically check for outdated actions on every pull request. This helps maintain security and ensures your team stays aware of available updates.\n\n\u003cdetails\u003e\n\u003csummary\u003eCreate \u003ccode\u003e.github/workflows/check-actions-updates.yml\u003c/code\u003e.\u003c/summary\u003e\n\n````yaml\nname: Check for outdated GitHub Actions\non:\n  pull_request:\n    types: [edited, opened, synchronize, reopened]\n\njobs:\n  check-actions:\n    name: Check for GHA updates\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n\n      - name: Install actions-up\n        run: npm install -g actions-up\n\n      - name: Run actions-up check\n        id: actions-check\n        run: |\n          echo \"## GitHub Actions Update Check\" \u003e\u003e $GITHUB_STEP_SUMMARY\n          echo \"\" \u003e\u003e $GITHUB_STEP_SUMMARY\n\n          # Initialize variables\n          HAS_UPDATES=false\n          UPDATE_COUNT=0\n\n          # Run actions-up and capture output\n          echo \"Running actions-up to check for updates...\"\n          actions-up --dry-run \u003e actions-up-raw.txt 2\u003e\u00261 || true\n\n          # Parse the output to detect updates\n          if grep -q \"→\" actions-up-raw.txt; then\n            HAS_UPDATES=true\n            # Count the number of updates (lines with arrows)\n            UPDATE_COUNT=$(grep -c \"→\" actions-up-raw.txt || echo \"0\")\n          fi\n\n          # Create formatted output\n          if [ \"$HAS_UPDATES\" = true ]; then\n            echo \"Found $UPDATE_COUNT GitHub Actions with available updates\" \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo \"\" \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo \"\u003cdetails\u003e\" \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo \"\u003csummary\u003eClick to see details\u003c/summary\u003e\" \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo \"\" \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo '```' \u003e\u003e $GITHUB_STEP_SUMMARY\n            cat actions-up-raw.txt \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo '```' \u003e\u003e $GITHUB_STEP_SUMMARY\n            echo \"\u003c/details\u003e\" \u003e\u003e $GITHUB_STEP_SUMMARY\n\n            # Create detailed markdown report with better formatting\n            {\n              echo \"## GitHub Actions Update Report\"\n              echo \"\"\n\n              echo \"### Summary\"\n              echo \"- **Updates available:** $UPDATE_COUNT\"\n              echo \"\"\n\n              # See the raw output above for details.\n              echo \"### How to Update\"\n              echo \"\"\n              echo \"You have several options to update these actions:\"\n              echo \"\"\n              echo \"#### Option 1: Automatic Update (Recommended)\"\n              echo '```bash'\n              echo \"# Run this command locally in your repository\"\n              echo \"npx actions-up\"\n              echo '```'\n              echo \"\"\n              echo \"#### Option 2: Manual Update\"\n              echo \"1. Review each update in the table above\"\n              echo \"2. For breaking changes, click the Release Notes link to review changes\"\n              echo \"3. Edit the workflows and update the version numbers\"\n              echo \"4. Test the changes in your CI/CD pipeline\"\n              echo \"\"\n              echo \"---\"\n              echo \"\"\n              echo \"\u003cdetails\u003e\"\n              echo \"\u003csummary\u003eRaw actions-up output\u003c/summary\u003e\"\n              echo \"\"\n              echo '```'\n              cat actions-up-raw.txt\n              echo '```'\n              echo \"\u003c/details\u003e\"\n            } \u003e actions-up-report.md\n\n            echo \"has-updates=true\" \u003e\u003e $GITHUB_OUTPUT\n            echo \"update-count=$UPDATE_COUNT\" \u003e\u003e $GITHUB_OUTPUT\n          else\n            echo \"All GitHub Actions are up to date!\" \u003e\u003e $GITHUB_STEP_SUMMARY\n\n            {\n              echo \"## GitHub Actions Update Report\"\n              echo \"\"\n              echo \"### All GitHub Actions in this repository are up to date!\"\n              echo \"\"\n              echo \"No action required. Your workflows are using the latest versions of all GitHub Actions.\"\n            } \u003e actions-up-report.md\n\n            echo \"has-updates=false\" \u003e\u003e $GITHUB_OUTPUT\n            echo \"update-count=0\" \u003e\u003e $GITHUB_OUTPUT\n          fi\n\n      - name: Comment PR with updates\n        if: github.event_name == 'pull_request'\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const fs = require('fs');\n            const report = fs.readFileSync('actions-up-report.md', 'utf8');\n            const hasUpdates = '${{ steps.actions-check.outputs.has-updates }}' === 'true';\n            const updateCount = '${{ steps.actions-check.outputs.update-count }}';\n\n            // Check if we already commented\n            const comments = await github.rest.issues.listComments({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number\n            });\n\n            const botComment = comments.data.find(comment =\u003e\n              comment.user.type === 'Bot' \u0026\u0026\n              comment.body.includes('GitHub Actions Update Report')\n            );\n\n            const commentBody = `${report}\n\n            ---\n            *Generated by [actions-up](https://github.com/azat-io/actions-up) | Last check: ${new Date().toISOString()}*`;\n\n            // Only comment if there are updates or if we previously commented\n            if (hasUpdates || botComment) {\n              if (botComment) {\n                // Update existing comment\n                await github.rest.issues.updateComment({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  comment_id: botComment.id,\n                  body: commentBody\n                });\n                console.log('Updated existing comment');\n              } else {\n                // Create new comment only if there are updates\n                await github.rest.issues.createComment({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: context.issue.number,\n                  body: commentBody\n                });\n                console.log('Created new comment');\n              }\n            } else {\n              console.log('No updates found and no previous comment exists - skipping comment');\n            }\n\n            // Add or update PR labels based on status\n            const labels = await github.rest.issues.listLabelsOnIssue({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              issue_number: context.issue.number\n            });\n\n            const hasOutdatedLabel = labels.data.some(label =\u003e label.name === 'outdated-actions');\n\n            if (hasUpdates \u0026\u0026 !hasOutdatedLabel) {\n              // Add label if updates are found\n              try {\n                await github.rest.issues.addLabels({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: context.issue.number,\n                  labels: ['outdated-actions']\n                });\n                console.log('Added outdated-actions label');\n              } catch (error) {\n                console.log('Could not add label (might not exist in repo):', error.message);\n              }\n            } else if (!hasUpdates \u0026\u0026 hasOutdatedLabel) {\n              // Remove label if no updates\n              try {\n                await github.rest.issues.removeLabel({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: context.issue.number,\n                  name: 'outdated-actions'\n                });\n                console.log('Removed outdated-actions label');\n              } catch (error) {\n                console.log('Could not remove label:', error.message);\n              }\n            }\n\n      - name: Fail if outdated actions found\n        if: steps.actions-check.outputs.has-updates == 'true'\n        run: |\n          echo \"::error:: Found ${{ steps.actions-check.outputs.update-count }} outdated GitHub Actions. Please update them before merging.\"\n          echo \"\"\n          echo \"You can update them by running: npx actions-up\"\n          echo \"Or manually update the versions in your workflows.\"\n          exit 1\n````\n\n\u003c/details\u003e\n\n### Scheduled Checks\n\nYou can also set up scheduled checks to stay informed about updates:\n\n```yaml\nname: Weekly Actions Update Check\n\non:\n  schedule:\n    - cron: '0 9 * * 1' # Every Monday at 9 AM\n  workflow_dispatch: # Allow manual triggers\n\njobs:\n  check-updates:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n      - run: npm install -g actions-up\n      - run: |\n          if actions-up --dry-run | grep -q \"→\"; then\n            echo \"Updates available! Run 'npx actions-up' to update.\"\n            exit 1\n          fi\n```\n\n## Example\n\n```yaml\n# Before\n- uses: actions/checkout@v3\n- uses: actions/setup-node@v3\n\n# After running actions-up\n- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0\n- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0\n```\n\n## Advanced Usage\n\n### Using GitHub Token for Higher Rate Limits\n\nWhile Actions Up works without authentication, providing a GitHub token increases API rate limits from 60 to 5000 requests per hour, useful for large projects:\n\n[Create a GitHub Personal Access Token](https://github.com/settings/tokens/new?scopes=public_repo\u0026description=actions-up).\n\n- For public repositories: Select `public_repo` scope\n- For private repositories: Select `repo` scope\n\nSet the token as an environment variable:\n\n```bash\nexport GITHUB_TOKEN=your_token_here\nnpx actions-up\n```\n\nOr in GitHub Actions:\n\n```yaml\n- name: Check for updates\n  env:\n    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  run: npx actions-up --dry-run\n```\n\n### Skipping Updates\n\nSkip updates using CLI excludes and YAML ignore comments. Excludes run first, then ignore comments.\n\n#### CLI Excludes\n\nSkip actions by name using regular expressions. Patterns are matched against the full action name (`owner/repo[/path]`).\n\n- Repeatable flag: `--exclude \u003cregex\u003e` (can be used multiple times)\n- Comma-separated list is supported inside a single flag\n- Forms:\n  - Plain string compiled as case-insensitive regex: `my-org/.*`\n  - Literal with flags: `/^actions\\/internal-.+$/i`\n\nExamples:\n\n```bash\nnpx actions-up --exclude \"my-org/.*\"\nnpx actions-up --exclude \".*/internal-.*\" --exclude \"/^acme\\/.+$/i\"\n# or\nnpx actions-up --exclude \"my-org/.*, .*/internal-.*\"\n```\n\n#### Ignore Comments\n\nYou can skip specific actions or files using YAML comments. Ignored items are hidden in dry-run and interactive modes and are not updated with `--yes`.\n\n- Ignore whole file: `# actions-up-ignore-file`\n- Block ignore: `# actions-up-ignore-start` … `# actions-up-ignore-end`\n- Next line: `# actions-up-ignore-next-line`\n- Inline on the same line: append `# actions-up-ignore`\n\nExample:\n\n```yaml\n# actions-up-ignore-file\n\n# actions-up-ignore-next-line\n- uses: actions/checkout@v3\n\n- uses: actions/setup-node@v3 # actions-up-ignore\n\n# actions-up-ignore-start\n- uses: actions/cache@v3\n# actions-up-ignore-end\n```\n\n## Security\n\nActions Up promotes security best practices:\n\n- **SHA pinning**: Uses commit SHA instead of mutable tags\n- **Version comment**: Adds the released version next to the pinned SHA for readability\n- **No Auto-Updates**: Full control over what gets updated\n- **Breaking Change Warnings**: Alerts you to major version updates that may require configuration changes\n\n## CI/CD Best Practices\n\nWhen using Actions Up in your CI/CD pipeline:\n\n1. **Start with warnings**: Begin by running checks without failing builds to gauge the update frequency\n2. **Regular updates**: Schedule weekly or monthly update PRs rather than blocking every PR\n3. **Team education**: Ensure your team understands the security benefits of keeping actions updated\n4. **Gradual adoption**: Roll out to a few repositories first before organization-wide deployment\n\n## Contributing\n\nSee [Contributing Guide](https://github.com/azat-io/actions-up/blob/main/contributing.md).\n\n## License\n\nMIT \u0026copy; [Azat S.](https://azat.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazat-io%2Factions-up","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fazat-io%2Factions-up","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fazat-io%2Factions-up/lists"}