{"id":13545873,"url":"https://github.com/dkhamsing/awesome_bot","last_synced_at":"2025-10-11T21:31:07.026Z","repository":{"id":38206715,"uuid":"47664932","full_name":"dkhamsing/awesome_bot","owner":"dkhamsing","description":":white_check_mark: Validate links in awesome projects","archived":false,"fork":false,"pushed_at":"2023-04-20T20:56:27.000Z","size":361,"stargazers_count":872,"open_issues_count":11,"forks_count":87,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-10-07T12:41:18.035Z","etag":null,"topics":["awesome","ci","circleci","cli","danger","links","readme","redirects","tool","travis-ci","verify"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":false,"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/dkhamsing.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":null}},"created_at":"2015-12-09T02:59:58.000Z","updated_at":"2025-09-17T00:31:53.000Z","dependencies_parsed_at":"2024-01-14T21:21:17.219Z","dependency_job_id":"106ab20d-d9ee-4606-ac30-a1054db47e1b","html_url":"https://github.com/dkhamsing/awesome_bot","commit_stats":{"total_commits":327,"total_committers":36,"mean_commits":9.083333333333334,"dds":0.4525993883792049,"last_synced_commit":"9cc99fd9004a8a948a453e755a92ed861db1fb68"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/dkhamsing/awesome_bot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkhamsing%2Fawesome_bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkhamsing%2Fawesome_bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkhamsing%2Fawesome_bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkhamsing%2Fawesome_bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dkhamsing","download_url":"https://codeload.github.com/dkhamsing/awesome_bot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dkhamsing%2Fawesome_bot/sbom","scorecard":{"id":346677,"data":{"date":"2025-08-11","repo":{"name":"github.com/dkhamsing/awesome_bot","commit":"9cc99fd9004a8a948a453e755a92ed861db1fb68"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Code-Review","score":4,"reason":"Found 12/29 approved changesets -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/dkhamsing/awesome_bot/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/dkhamsing/awesome_bot/ci.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:1: pin your Docker image by updating ruby:alpine to ruby:alpine@sha256:e284f39a2103a564dca9771a81bfecb455b04cd3be4149b133ed7e508ef1b65f","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 19 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T07:12:42.794Z","repository_id":38206715,"created_at":"2025-08-18T07:12:42.794Z","updated_at":"2025-08-18T07:12:42.794Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279005967,"owners_count":26084004,"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-11T02:00:06.511Z","response_time":55,"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":["awesome","ci","circleci","cli","danger","links","readme","redirects","tool","travis-ci","verify"],"created_at":"2024-08-01T12:00:24.786Z","updated_at":"2025-10-11T21:31:06.726Z","avatar_url":"https://github.com/dkhamsing.png","language":"Ruby","funding_links":[],"categories":["HarmonyOS","介绍","Ruby","Testing","Automation and tasking"],"sub_categories":["Windows Manager","Others","Observability"],"readme":"# awesome_bot\n\nVerify links in [awesome](status/status.md) projects\n\n![](http://i.giphy.com/urvsFBDfR6N32.gif)\n\n[![Gem Version](https://badge.fury.io/rb/awesome_bot.svg)](https://badge.fury.io/rb/awesome_bot)\n[![](https://img.shields.io/badge/awesome-status-brightgreen.svg)](status/status.md)\n![Test](https://github.com/dkhamsing/awesome_bot/actions/workflows/ci.yml/badge.svg)\n\n`awesome_bot` checks for valid URLs in a file, it can be used to [verify pull requests](#validate-pull-requests) updating a README.\n\n## Installation\n\n    $ gem install awesome_bot\n\n## Usage\n\n### Command Line\n\n``` shell\nUsage: awesome_bot [file or files]\n       awesome_bot [options]\n    -f, --files [files]              Comma separated files to check\n    -a, --allow [errors]             Status code errors to allow\n        --allow-dupe                 Duplicate URLs are allowed\n        --allow-ssl                  SSL errors are allowed\n        --allow-redirect             Redirected URLs are allowed\n        --allow-timeout              URLs that time out are allowed\n        --base-url [base url]        Base URL to use for relative links\n    -d, --request-delay [seconds]    Set request delay\n    -t, --set-timeout [seconds]      Set connection timeout (default: 30)\n        --skip-save-results          Skip saving results\n    -w, --white-list [urls]          Comma separated URLs to white list\n```\n\n- You can check multiple files (comma separated or `*` pattern, look below for details).\n\n- By default, duplicate URLs or any status code other than `200` are flagged as failures.\n\n  - Use option `--allow-dupe` to allow duplicates.\n  - Use option `--allow-redirect` to allow redirects.\n  - Use option `--allow` to allow specific status code errors.\n  - Use option `--white-list` (`-w` for short) to prevent links from being flagged: `-w domain1.com/post/article,domain2.com` white lists `domain1.com/post/article` and all links matching `domain2.com`.\n\n### Examples\n\n```shell\n$ awesome_bot README.md\n\u003e Checking links in README.md\nLinks found: 56, 37 unique\n  01. https://github.com/sindresorhus/awesome\n  02. http://i.giphy.com/urvsFBDfR6N32.gif\n  03. https://travis-ci.org/dkhamsing/awesome_bot.svg\n# ...\n  37. https://github.com/dkhamsing\n  Checking URLs: ✓✓✓→?✓→✓→→✓✓→✓✓✓→✓✓✓✓✓✓✓✓✓✓✓→✓✓✓✓✓→✓✓\n\nIssues :-(\n\u003e Links\n  1. [L007] 301 https://travis-ci.org/dkhamsing/awesome_bot.svg → https://api.travis-ci.org/dkhamsing/awesome_bot.svg\n  2. [L008] 302 https://badge.fury.io/rb/awesome_bot → http://rubygems.org/gems/awesome_bot\n# ...\n\u003e Dupes\n  1. [L03] https://github.com/sindresorhus/awesome\n  2. [L05] http://i.giphy.com/urvsFBDfR6N32.gif\n# ...\n```\n\n```shell\n$ awesome_bot README.md --allow-dupe --allow-redirect -w rubydoc,giphy\n# allow redirects, dupes and white list all links matching rubydoc and giphy\n\n$ awesome_bot README.md,README-zh.md\n# check links in 2 files\n\n$ awesome_bot docs/*.md\n# check all Markdown files in the docs/ directory\n\n$ awesome_bot README.md --allow-timeout -t 5\n# speed up validation by setting a timeout of 5 seconds per link request and allowing timeouts\n\n$ awesome_bot README.md --allow 403,429\n# allow status code errors 403 and 429\n# --allow 301 would be similar to --allow-redirect\n\n$ awesome_bot README.md --base-url https://github.com/IDR/idr-notebooks/blob/master/\n# check relative links using the base URL provided\n```\n\n```shell\n(master) $ git branch\n* master\n(master) $ git checkout -b new-branch\nSwitched to a new branch 'new-branch'\n(new-branch) $ touch new-readme.md \u0026\u0026 echo 'https://github.com/dkhamsing' \u003e\u003e new-readme.md\n(new-branch) $ git add new-readme.md\n(new-branch) $ git commit -m 'Testing'\n[new-branch ef47336] Testing\n 1 file changed, 1 insertion(+)\n create mode 100644 new-readme.md\n(new-branch) $ git diff master.. --name-only | grep '.md' | xargs awesome_bot\n\u003e Checking links in new-readme.md\nLinks to check: 1\n  1. https://github.com/dkhamsing\nChecking URLs: ✓\nNo issues :-)\n\nWrote results to ab-results-new-readme.md.json\n```\n\n### Docker Examples\nIf you do not want to install Ruby or its dependencies you can simply use Docker and Docker image.\n\nHere is an example for checking the links in the Markdown files in your current directory/subdirectories:\n```shell\ndocker run -ti --rm -v $PWD:/mnt:ro dkhamsing/awesome_bot --white-list \"test.com\" --allow-dupe --allow-redirect --skip-save-results `find . -name \"*.md\"`\n```\n\nor just check the links in a single file located at `./templates/ubuntu.md`:\n\n```shell\ndocker run -ti --rm -v $PWD:/mnt:ro dkhamsing/awesome_bot --allow-dupe --allow-redirect --skip-save-results ./templates/ubuntu.md\n```\n\nYou always need to specify the path to the file so you cannot simply use `*.md`; instead use `ls *.md\"`:\n```shell\ndocker run -ti --rm -v $PWD:/mnt:ro dkhamsing/awesome_bot --white-list \"test.com\" --allow-dupe --allow-redirect --skip-save-results `ls *.md`\n```\n\n### Library\n\n```ruby\nirb(main):001:0\u003e require 'awesome_bot'\n=\u003e true\nirb(main):002:0\u003e content = File.read 'README.md'\n=\u003e \"...\"\nirb(main):003:0\u003e result = AwesomeBot.check content\n=\u003e #\u003cAwesomeBot::Result:0x007fdde39f4408 @links=...\u003e\n# AwesomeBot Result with success, statuses_issues, dupes and more\nirb(main):004:0\u003e puts result.success ? 'No errors' : ':-('\n:-(\n```\n\nMore information at [rubydoc](http://www.rubydoc.info/gems/awesome_bot).\n\n## Validate Pull Requests\n\nDoes your GitHub README contain a lot of links? `awesome_bot` can help you validate them when a [pull request](https://github.com/dkhamsing/open-source-ios-apps/pull/159) is created (or a commit is pushed). It is used by:\n\n- https://github.com/tiimgreen/github-cheat-sheet\n- https://github.com/enaqx/awesome-react\n- https://github.com/ziadoz/awesome-php\n- https://github.com/vsouza/awesome-ios\n- https://github.com/alebcay/awesome-shell\n- https://github.com/matteocrippa/awesome-swift\n\nand [more](status/status.md).\n\nTips\n\n- Use the keyword [`[ci skip]`](https://docs.travis-ci.com/user/customizing-the-build/) in your commit title/message to skip verification.\n- Use [Danger](#danger).\n\n### GitHub Actions\n\nTo use `awesome_bot` with GitHub Actions (workflows), here is an [example](https://github.com/dkhamsing/open-source-ios-apps/blob/master/.github/workflows/ruby.yml):\n\n```yml\nname: Ruby\n\non:\n  push:\n    branches: [ '*' ]\n  pull_request:\n    branches: [ '*' ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v3\n    - name: Set up Ruby 2.6\n      uses: ruby/setup-ruby@v1\n      with:\n        ruby-version: '2.6'\n    - name: Checks\n      run: |\n        gem install awesome_bot\n        awesome_bot check-unique.txt --allow-ssl -a 302,429 -w xbmc/xbmc\n```\n\n### Travis CI\n\nTo use `awesome_bot` with Travis CI, [connect your repo](https://travis-ci.org/) and create a [`.travis.yml` file](https://github.com/ziadoz/awesome-php/blob/master/.travis.yml).\n\n```yml\nlanguage: ruby\nrvm: 2.4.1\nbefore_script: gem install awesome_bot\nscript: awesome_bot README.md\n```\n\nTo turn off email notifications, add the lines below\n\n```yml\nnotifications:\n  email: false\n```\n\nIn case you want to use the docker image inside Travis CI follow this example which will check broken links in all `*.md` files in your repository:\n\n```yml\nsudo: required\n\nservices:\n  - docker\n\nscript:\n  # Link Checks\n  - docker run -ti --rm -v $PWD:/mnt:ro dkhamsing/awesome_bot --allow-dupe --allow-redirect --skip-save-results `find . -name \"*.md\"`\n```\n\n### More\n\n[CircleCI](https://circleci.com), [Codeship](https://codeship.com/), and [Semaphore CI](https://semaphoreci.com/) support running tests without adding a file to the repo (a public configuration file can however help others contribute).\n\n```\n# Codeship\nSetup\nrvm use 2.4.1 --install\ngem install awesome_bot\n\nTest\nawesome_bot README.md\n```\n\n```\n# Semaphore CI\nLanguage: Ruby\nRuby version: 2.4.1\nDatabases for: don't generate\nSetup:\ngem install awesome_bot\nawesome_bot README.md\n```\n\n### Status Badge\n\n[![Build Status](https://travis-ci.org/unixorn/awesome-zsh-plugins.svg)](https://travis-ci.org/unixorn/awesome-zsh-plugins)\n\nTo add the Travis CI build status badge above to your project, use the following code\n\n```\n[![Build Status](https://travis-ci.org/\u003cusername\u003e/\u003cproject\u003e.svg)](https://travis-ci.org/\u003cusername\u003e/\u003cproject\u003e)\n\ni.e.\n[![Build Status](https://travis-ci.org/dkhamsing/awesome_bot.svg?branch=master)](https://travis-ci.org/dkhamsing/awesome_bot)\n```\n\nAs it happens, the default code snippet provided contains a redirect so adding a badge could fail your status :sob:.. one way to fix this is to white list `travis-ci`, i.e.\n\n```\n- awesome_bot README.md --white-list travis-ci\n```\n\nYou can also add a badge for other CI tools, check out [shields.io](https://shields.io/).\n\n### Danger\n\nIntegrate `awesome_bot` with [Danger](https://github.com/danger/danger) and have results reported back to the [pull request](https://github.com/vsouza/awesome-ios/pull/1001).\n\n![danger](https://cloud.githubusercontent.com/assets/4723115/17375716/0cdd37cc-5967-11e6-8ae3-829060a786dc.png)\n\nHere's the step in your **Dangerfile**:\n\n```ruby\n# Check links\nrequire 'json'\nresults = File.read 'ab-results-README.md-markdown-table.json'\nj = JSON.parse results\nif j['error']==true\n  fail j['title']\n  markdown j['message']\nend\n```\n\n## Contact\n\n- [github.com/dkhamsing](https://github.com/dkhamsing)\n- [twitter.com/dkhamsing](https://twitter.com/dkhamsing)\n\n## License\n\nThis project is available under the MIT license. See the [LICENSE](LICENSE) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkhamsing%2Fawesome_bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdkhamsing%2Fawesome_bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdkhamsing%2Fawesome_bot/lists"}