├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── SUPPORT.md └── workflows │ ├── daily-check.yml │ ├── lint-and-deploy-on-push-to-main.yml │ └── run-tests.yml ├── .gitignore ├── .prettierrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── HOW-TO-CONFIGURE.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── __tests__ ├── __fixtures__ │ ├── repolinter.js │ ├── results-passed.js │ └── results.js ├── __mocks__ │ ├── @octokit │ │ └── rest.js │ ├── chalk.js │ └── repolinter.js ├── __snapshots__ │ └── utils.test.js.snap └── utils.test.js ├── diagrams └── activity.puml ├── frontend ├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── README.md ├── babel.config.js ├── deploy.sh ├── package-lock.json ├── package.json ├── public │ ├── frontend.json │ ├── index.html │ ├── logo.png │ ├── logo.svg │ └── robots.txt ├── src │ ├── App.vue │ ├── assets │ │ ├── box.svg │ │ ├── check-circle.svg │ │ ├── external-link.svg │ │ ├── logo.png │ │ └── x-circle.svg │ ├── components │ │ ├── Details.vue │ │ ├── Footer.vue │ │ ├── Healthy.vue │ │ └── Navbar.vue │ ├── main.js │ ├── registerServiceWorker.js │ ├── router │ │ └── index.js │ ├── store │ │ └── index.js │ └── views │ │ ├── About.vue │ │ ├── Home.vue │ │ └── Rules.vue └── vue.config.js ├── package-lock.json ├── package.json ├── repolinter.json ├── reports └── REPORTS.md └── src ├── index.js └── utils.js /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # default owners the repo 2 | * @discombobulateme 3 | # Paloma Oliveira 4 | * @christian-bromann 5 | # Christian Bromann 6 | * @diemol 7 | # Diego Molina 8 | 9 | 10 | # Samples for assigning codeowners below: 11 | 12 | # Order is important; the last matching pattern takes the most 13 | # precedence. When someone opens a pull request that only 14 | # modifies JS files, only @js-owner and not the global 15 | # owner(s) will be requested for a review. 16 | # *.js @js-owner 17 | 18 | # You can also use email addresses if you prefer. They'll be 19 | # used to look up users just like we do for commit author 20 | # emails. 21 | # *.go docs@example.com 22 | 23 | # In this example, @doctocat owns any files in the build/logs 24 | # directory at the root of the repository and any of its 25 | # subdirectories. 26 | # /build/logs/ @doctocat 27 | 28 | # The `docs/*` pattern will match files like 29 | # `docs/getting-started.md` but not further nested files like 30 | # `docs/build-app/troubleshooting.md`. 31 | # docs/* docs@example.com 32 | 33 | # In this example, @octocat owns any file in an apps directory 34 | # anywhere in your repository. 35 | # apps/ @octocat 36 | 37 | # In this example, @doctocat owns any file in the `/docs` 38 | # directory in the root of your repository. 39 | # /docs/ @doctocat 40 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 1. 11 | 1. 12 | 13 | ## Specifications 14 | 15 | - Version: 16 | - Platform: 17 | - Subsystem: 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # One-line summary 2 | 3 | > Issue : #1234 (only if appropriate) 4 | 5 | ## Description 6 | A few sentences describing the overall goals of the pull request's 7 | commits. 8 | 9 | ## Types of Changes 10 | _What types of changes does your code introduce? Keep the ones that apply:_ 11 | 12 | - New feature (non-breaking change which adds functionality) 13 | - Bug fix (non-breaking change which fixes an issue) 14 | - Configuration change 15 | - Refactor/improvements 16 | - Documentation / non-code 17 | 18 | ## Tasks 19 | _List of tasks you will do to complete the PR_ 20 | - [ ] Created Task 1 21 | - [ ] Created Task 2 22 | - [ ] To-do Task 3 23 | 24 | ## Review 25 | _List of tasks the reviewer must do to review the PR_ 26 | - [ ] Tests 27 | - [ ] Documentation 28 | - [ ] CHANGELOG 29 | 30 | ## Deployment Notes 31 | These should highlight any db migrations, feature toggles, etc. 32 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Getting help with _projectname_ 2 | 3 | Thanks for using Automated OSS Quality Check. Before filing an issue, there are a few places 4 | to explore and pieces to put together to make the process as smooth as possible. 5 | 6 | First, let's figure out where to ask: 7 | 8 | * If it's a question on a Sauce Labs specific platform feature, send an email to [support@saucelabs.com](support@saucelabs.com). 9 | * If it's a question on using this specific project, file an issue. 10 | * If it's a bug: you're in the right place, please also file an issue. 11 | 12 | Before opening a new issue, be sure to [search issues and pull requests](https://github.com/saucelabs/_projectname_/issues) to make sure the bug hasn't been reported and/or already fixed in the development version. By default, the search will be pre-populated with `is:issue is:open`. You can [edit the qualifiers](https://help.github.com/articles/searching-issues-and-pull-requests/) (e.g. `is:pr`, `is:closed`) as needed. For example, you'd simply remove `is:open` to search _all_ issues in the repo, open or closed. 13 | 14 | The maintainer team is committed to respond to your request within a timeframe of _projectSLATime_ hrs. 15 | 16 | Thanks for your help! 17 | -------------------------------------------------------------------------------- /.github/workflows/daily-check.yml: -------------------------------------------------------------------------------- 1 | name: Verify Repo Health Daily 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | Lint-Deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Gives access to repository 12 | uses: actions/checkout@v2 13 | 14 | - name: Setup Node version 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: '12' 18 | 19 | - name: Install dependencies 20 | run: npm install 21 | 22 | - name: Generate frontend data 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | run: node src/index.js 26 | 27 | - name: Install Frontend 28 | run: cd frontend && npm install 29 | 30 | - name: Build Vue 31 | run: cd frontend && npm run build 32 | 33 | - name: Deploy Vue Site 34 | uses: peaceiris/actions-gh-pages@v3 35 | with: 36 | github_token: ${{ secrets.GITHUB_TOKEN }} 37 | publish_dir: ./frontend/dist 38 | publish_branch: gh-pages 39 | user_name: 'OSS Check My Repo' 40 | user_email: 'oss-check-my-repo-bot@users.noreply.github.com' 41 | commit_message: ${{ github.event.head_commit.message }} 42 | -------------------------------------------------------------------------------- /.github/workflows/lint-and-deploy-on-push-to-main.yml: -------------------------------------------------------------------------------- 1 | name: Lint And Deploy On Push To Main 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | Lint-Deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Gives access to repository 13 | uses: actions/checkout@v2 14 | 15 | - name: Setup Node version 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: '12' 19 | 20 | - name: Install dependencies 21 | run: npm install 22 | 23 | - name: Generate frontend data 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | run: node src/index.js 27 | 28 | - name: Generate Artifact 29 | uses: actions/upload-artifact@v2 30 | with: 31 | name: my-artifact 32 | path: frontend/public/frontend.json 33 | 34 | - name: Install Frontend 35 | run: cd frontend && npm install 36 | 37 | - name: Build Vue 38 | run: cd frontend && npm run build 39 | 40 | - name: Deploy Vue Site 41 | uses: peaceiris/actions-gh-pages@v3 42 | with: 43 | github_token: ${{ secrets.GITHUB_TOKEN }} 44 | publish_dir: ./frontend/dist 45 | publish_branch: gh-pages 46 | user_name: 'OSS Check My Repo' 47 | user_email: 'oss-check-my-repo-bot@users.noreply.github.com' 48 | commit_message: ${{ github.event.head_commit.message }} 49 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Run tests on every commit 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | steps: 11 | # Add node 12 | - name: Setup Node version 13 | uses: actions/setup-node@v1 14 | with: 15 | node-version: '12' 16 | 17 | # Add a project to work on 18 | - name: Clone Repository 19 | uses: actions/checkout@v2 20 | 21 | # Install dependencies 22 | - name: Install dependencies 23 | run: npm install 24 | 25 | # Which file to act upon 26 | - name: Run tests 27 | run: npm test 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # Snowpack dependency directory (https://snowpack.dev/) 45 | web_modules/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | .parcel-cache 78 | 79 | # Next.js build output 80 | .next 81 | out 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and not Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # Stores VSCode versions used for testing VSCode extensions 109 | .vscode-test 110 | 111 | # yarn v2 112 | .yarn/cache 113 | .yarn/unplugged 114 | .yarn/build-state.yml 115 | .yarn/install-state.gz 116 | .pnp.* 117 | 118 | # others 119 | .DS_Store 120 | 121 | # gitignored in the original project 122 | coverage/ 123 | tmp/ 124 | .idea/ 125 | vendor/ 126 | .bundle 127 | out 128 | .vscode/ 129 | 130 | # ignore created directies 131 | /reports 132 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid", 4 | "printWidth": 120, 5 | "semi": false, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at opensource@saucelabs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Check-My-Repo 2 | 3 | **Thank you for your interest in Check-My-Repo. Your contributions are highly welcome.** 4 | 5 | There are multiple ways of getting involved: 6 | 7 | - [Contributing to Check-My-Repo](#contributing-to-check-my-repo) 8 | - [Report a bug](#report-a-bug) 9 | - [Suggest a feature](#suggest-a-feature) 10 | - [Contribute code](#contribute-code) 11 | - [Commit messages](#commit-messages) 12 | - [Sign your work / Developer certificate of origin](#sign-your-work--developer-certificate-of-origin) 13 | 14 | Below are a few guidelines we would like you to follow. 15 | If you need help, please reach out to us by opening an issue. 16 | 17 | ## Report a bug 18 | Reporting bugs is one of the best ways to contribute. Before creating a bug report, please check that an [issue](/issues) reporting the same problem does not already exist. If there is such an issue, you may add your information as a comment. 19 | 20 | To report a new bug you should open an issue that summarizes the bug and set the label to "bug". 21 | 22 | If you want to provide a fix along with your bug report: That is great! In this case please send us a pull request as described in section [Contribute Code](#contribute-code). 23 | 24 | ## Suggest a feature 25 | To request a new feature you should open an [issue](../../issues/new) and summarize the desired functionality and its use case. Set the issue label to "feature". 26 | 27 | ## Contribute code 28 | This is an outline of what the workflow for code contributions looks like 29 | 30 | - Check the list of open [issues](../../issues). Either assign an existing issue to yourself, or 31 | create a new one that you would like work on and discuss your ideas and use cases. 32 | 33 | It is always best to discuss your plans beforehand, to ensure that your contribution is in line with our goals. 34 | 35 | - Fork the repository on GitHub 36 | - Create a topic branch from where you want to base your work. This is usually master. 37 | - Open a new pull request, label it `work in progress` and outline what you will be contributing 38 | - Make commits of logical units. 39 | - Make sure you sign-off on your commits `git commit -s -m "adding X to change Y"` 40 | - Write good commit messages (see below). 41 | - Push your changes to a topic branch in your fork of the repository. 42 | - As you push your changes, update the pull request with new infomation and tasks as you complete them 43 | - Project maintainers might comment on your work as you progress 44 | - When you are done, remove the `work in progess` label and ping the maintainers for a review 45 | - Your pull request must receive a :thumbsup: from two [maintainers](MAINTAINERS) 46 | 47 | Thanks for your contributions! 48 | 49 | ### Commit messages 50 | Your commit messages ideally can answer two questions: what changed and why. The subject line should feature the “what” and the body of the commit should describe the “why”. 51 | 52 | When creating a pull request, its description should reference the corresponding issue id. 53 | 54 | ### Sign your work / Developer certificate of origin 55 | All contributions (including pull requests) must agree to the Developer Certificate of Origin (DCO) version 1.1. This is exactly the same one created and used by the Linux kernel developers and posted on http://developercertificate.org/. This is a developer's certification that he or she has the right to submit the patch for inclusion into the project. Simply submitting a contribution implies this agreement, however, please include a "Signed-off-by" tag in every patch (this tag is a conventional way to confirm that you agree to the DCO) - you can automate this with a [Git hook](https://stackoverflow.com/questions/15015894/git-add-signed-off-by-line-using-format-signoff-not-working) 56 | 57 | ``` 58 | git commit -s -m "adding X to change Y" 59 | ``` 60 | 61 | **Have fun, and happy hacking!** 62 | -------------------------------------------------------------------------------- /HOW-TO-CONFIGURE.md: -------------------------------------------------------------------------------- 1 | # How to configure/ personalize check-my-repo 2 | 3 | Follow a few instructions on how to configure/ personalize your check-my-repo application 4 | 5 | ## Configuring Environment Variables/ GitHub Secrets 6 | 7 | When running locally it is important to provide a GITHUB_TOKEN to avoid rate limiting. To know more about it, visit: [GitHub documentation](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#:~:text=When%20using%20the%20built%2Din,to%2060%20requests%20per%20hour.) 8 | 9 | This will not happen when running through CI/CD as it is set up as authenticated user using GutHub’s default secret: GITHUB_TOKEN. You can change this at: src/index.js line 2: 10 | 11 | ``` 12 | const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }) 13 | ``` 14 | 15 | ## Personalizing CSS Style 16 | 17 | Application main configuration is defined at `./frontend/src/App.vue`. 18 | 19 | Although Vue works with scoped styles, most of the application styles are defined in variables, which makes changes easy and simple. 20 | 21 | ``` 22 | :root { 23 | --app-background: #464B54; 24 | --square-background-color: #2E3137; 25 | --passed-color: #158906; 26 | --passed-color-accent: #8CFF4D; 27 | --failed-color: #e12726; 28 | --primary-color: #6ED6FF; 29 | --grey-accent: lightgrey; 30 | --shadow: rgb(34, 33, 33); 31 | } 32 | ``` 33 | 34 | ## Changing Rules 35 | 36 | Check-My-Repo is built upon [Repolinter](https://todogroup.github.io/repolinter/), but does not used all their default rules as default. 37 | 38 | To add [see all Repolinter rules](https://github.com/todogroup/repolinter/blob/master/rulesets/default.json) please refer directly to their documentation. Check-My-Repo rules can be modified at `./repolinter.json` file in the project root. 39 | 40 | ### Changing Badges With Modified Rules 41 | 42 | If ou do change a rule, make sure to change your badges. 43 | 44 | This is the default ruleset badges, found at: `./frontend/src/components/Details.vue` 45 | 46 | ``` 47 | Binaries 48 | License 49 | Readme 50 | Changelog 51 | Contributing 52 | Ownership 53 | TestDir 54 | CodeOfConduct 55 | LicenseOnReadme 56 | Security 57 | Support 58 | ``` 59 | Where: 60 | - [] `item.includes` searches for the rule name specified in `repolinter.json` 61 | - [] `high`, `medium` or `low` changes the css style of the badges 62 | 63 | ## Changing Logo 64 | 65 | Application uses now Sauce Labs Bot as a default logo. You can change it to yout own logo just switching the `logo.svg` file at `./frontend/public` folder. 66 | 67 | ## Checking for accessibility after modifying the application 68 | 69 | Check-My-Repo uses [vue-axe](https://www.npmjs.com/package/vue-axe) in development mode to acessibility verification. 70 | 71 | You can check if something is missing on your Browsers console, or disable it in `./frontend/main.js` file, by turning to `auto: false` 72 | 73 | ``` 74 | if (process.env.NODE_ENV === 'development') { 75 | const VueAxe = require('vue-axe').default 76 | Vue.use(VueAxe, { 77 | auto: true // enable auto check. 78 | }) 79 | ``` 80 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Sauce Labs Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | Paloma Oliveira 2 | OSPO Open Source Program Office 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # (Ͼ˳Ͽ)...check-my-repo!!! 3 | 4 | 5 | https://user-images.githubusercontent.com/7980624/118667671-7fdc9d80-b7f4-11eb-8d67-e7e0094780af.mov 6 | 7 | 8 | Aiming to help Open Source Software OSS maintainers we, at the [Sauce Labs Open Source Program Office](https://opensource.saucelabs.com/), created [Check-My-Repo](https://opensource.saucelabs.com/check-my-repo/). 9 | An automated tool built upon [Repolinter](https://todogroup.github.io/repolinter/), that verifies if the main necessary parameters to comply with [open source best practices](https://opensource.guide/building-community/): from Readme to License, are present in the organizations or users repositories. 10 | By automating this verification open source projects maintenance is more effective and effortless, and can help you and your organization to have compliant software projects easier to service, test, upgrade, and maintain. 11 | Built with [Node.js](https://nodejs.org/en/), [Repolinter](https://www.npmjs.com/package/repolinter) and [Vue.js](https://v3.vuejs.org/), it is designed to run locally and automated, displaying results on your organization’s or user’s GitHub Page. 12 | 13 | Meant to be as easy as possible to enable right away usage, all you need to do is: fork it, and enable Pages choosing gh-pages as your GitHub pages repository. That easy 😊. 14 | 15 | ## How to adopt it into my organization? 16 | 17 | 1. Fork it 18 | 2. Enable Actions on Settings/ Actions Permissions 19 | 3. Enable Pages on Settings/ Pages by choosing gh-pages as your GitHub pages repository 20 | 21 | https://user-images.githubusercontent.com/7980624/117662543-f566bf00-b19f-11eb-85d2-9bd937d1907b.mov 22 | 23 | Using GitHub Actions and default environment variables, it will automatically get our user/ organization public information. 24 | 25 | **Please note** that, as Actions are planned to run once a day on cron: '0 0 * * *' time, or when a push is made to the main branch, you need to wait until your organization/ user information is updated in the page. 26 | 27 | It is designed to be as neutral as possible and comply with A11y accessibility guidelines. But, of course, you can modify all you want, it is open sourced under MIT license. Check [How to Configure](#HOW-TO-CONFIGURE) file to know how to do it. 28 | 29 | ## Command Line Step By Step & Running It Locally 30 | 31 | 1. [Fork](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo) [this project](https://github.com/saucelabs/check-my-repo) 32 | 33 | 2. Navigate in your terminal into the director you want to clone the repository, for example: 34 | 35 | ``` 36 | cd Documents 37 | 38 | ``` 39 | 40 | 3. Clone your fork (remember to change "YOUR ORGANIZATION") 41 | 42 | ``` 43 | git clone https://github.com//check-my-repo.git 44 | 45 | ``` 46 | 47 | 4. Open the cloned directory 48 | 49 | ``` 50 | cd check-my-repo 51 | 52 | ``` 53 | 54 | 5. Open the repository on your favorite code editor. If you are using VSC you can use `.code` to open your code editor 55 | 56 | 6. Install dependencies 57 | 58 | ``` 59 | npm install 60 | ``` 61 | 62 | 7. To run it locally, run the script: 63 | 64 | ``` 65 | node src/index.js 66 | ``` 67 | 68 | It enables you to verify all of your organization’s or user’s public repositories. 69 | You need to do this process at least once, as this generates a frontend.json file on the frontend/public folder, which will be used to display the information in Browser. 70 | 71 | 8. Now let’s install your frontend application: 72 | 73 | ``` 74 | cd frontend 75 | ``` 76 | 77 | 9. Install frontend dependencies 78 | ``` 79 | npm install 80 | ``` 81 | 82 | 10. Run server locally 83 | 84 | ``` 85 | npm run serve 86 | ``` 87 | 88 | 14. Open link provided in terminal 89 | 90 | ``` 91 | Cmd + click 92 | ``` 93 | 94 | That’s it! 95 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | We acknowledge that every line of code that we write may potentially contain security issues. 2 | We are trying to deal with it responsibly and provide patches as quickly as possible. 3 | 4 | Please contact us via [E-Mail](mailto:opensource@saucelabs.com) immediately after discovery of the vulnerability. Thanks! -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # How to get support 2 | 3 | In case you need help either using, contributing or modifying check-my-repo, please contact us directly by email 🙂 4 | 5 | ## Please include it in your email: 6 | - [ ] Title: brief description of what you need 7 | - [ ] Body of email: detailed description of the problem you are experiencing, how you have tried to solve it, and how you think we can help. 8 | 9 | We will reply as soon as possible. 10 | 11 | Paloma Oliveira 12 | OSPO Open Source Program Office 13 | 14 | -------------------------------------------------------------------------------- /__tests__/__fixtures__/repolinter.js: -------------------------------------------------------------------------------- 1 | export const repolinterNewModelResult = {} 2 | -------------------------------------------------------------------------------- /__tests__/__fixtures__/results-passed.js: -------------------------------------------------------------------------------- 1 | const resultsPassed = [ 2 | { 3 | lintResult: { 4 | passed: true, 5 | }, 6 | ruleInfo: { 7 | name: 'passed-repo', 8 | }, 9 | }, 10 | { 11 | lintResult: { 12 | passed: true, 13 | }, 14 | ruleInfo: { 15 | name: 'passed-repo', 16 | }, 17 | }, 18 | ] 19 | 20 | module.exports = resultsPassed 21 | -------------------------------------------------------------------------------- /__tests__/__fixtures__/results.js: -------------------------------------------------------------------------------- 1 | const results = [ 2 | { 3 | lintResult: { 4 | passed: true, 5 | }, 6 | ruleInfo: { 7 | name: 'passed-repo', 8 | }, 9 | }, 10 | { 11 | lintResult: { 12 | passed: false, 13 | }, 14 | ruleInfo: { 15 | name: 'failing-repo', 16 | }, 17 | }, 18 | ] 19 | 20 | module.exports = results 21 | -------------------------------------------------------------------------------- /__tests__/__mocks__/@octokit/rest.js: -------------------------------------------------------------------------------- 1 | /* Variable to store the instance of Octokit class and make it available to test */ 2 | const createdInstances = [] 3 | /* Mocks Octokit API functionality */ 4 | class Octokit { 5 | constructor() { 6 | this.repos = { 7 | listReleases: jest.fn().mockImplementation(({ owner, repo, per_page }) => { 8 | if (repo === 'repository without releases') { 9 | return { 10 | data: [], 11 | } 12 | } 13 | /* An empty objetct is an information in the array */ 14 | return { data: [{}] } 15 | }), 16 | } 17 | /* Stores instantiation */ 18 | createdInstances.push(this) 19 | } 20 | } 21 | 22 | module.exports = { Octokit, createdInstances } 23 | -------------------------------------------------------------------------------- /__tests__/__mocks__/chalk.js: -------------------------------------------------------------------------------- 1 | const chalk = jest.fn().mockImplementation((...args) => { 2 | return args.join(' ') 3 | }) 4 | 5 | module.exports = chalk 6 | -------------------------------------------------------------------------------- /__tests__/__mocks__/repolinter.js: -------------------------------------------------------------------------------- 1 | const { results } = require('../__fixtures__/results') 2 | 3 | const repolinter = { 4 | runRuleset: true, 5 | lint: jest.fn().mockReturnValue(Promise.resolve(results)), 6 | jsonFormatter: { 7 | formatOutput: jest.fn().mockReturnValue(Promise.resolve(JSON.stringify({ hello: 1 }))), 8 | }, 9 | } 10 | module.exports = repolinter 11 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/utils.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`should filter passed results 1`] = ` 4 | Array [ 5 | Array [ 6 | "{bgBlue Repository: ,} repository", 7 | ], 8 | Array [ 9 | " 10 | {hex('#FF8800') 🚨 ,} failing-repo", 11 | ], 12 | Array [ 13 | " 14 | {greenBright ✅ ,} passed-repo", 15 | ], 16 | Array [ 17 | " 18 | ", 19 | ], 20 | ] 21 | `; 22 | 23 | exports[`should return global all passed when there is no fail 1`] = ` 24 | Array [ 25 | Array [ 26 | "{bgBlue Repository: , 27 | } 28 | {greenBright Passed all checks 🥳 29 | } repository", 30 | ], 31 | ] 32 | `; 33 | -------------------------------------------------------------------------------- /__tests__/utils.test.js: -------------------------------------------------------------------------------- 1 | const { printResults, createJsonFile, validateChangeLog } = require('../src/utils') 2 | const results = require('./__fixtures__/results') 3 | const resultsPassed = require('./__fixtures__/results-passed') 4 | const { createdInstances } = require('@octokit/rest') 5 | 6 | const fs = require('fs') 7 | jest.mock('fs') 8 | fs.promises = { mkdir: jest.fn(), writeFile: jest.fn() } 9 | 10 | const repository = 'repository' 11 | const organization = 'organization' 12 | 13 | test('should filter passed results', () => { 14 | const data = { name: 'repository' } 15 | const log = jest.fn() 16 | printResults(data, results, log) 17 | 18 | expect(log.mock.calls).toMatchSnapshot() 19 | }) 20 | 21 | test('should return global all passed when there is no fail', () => { 22 | const data = { name: 'repository' } 23 | const log = jest.fn() 24 | printResults(data, resultsPassed, log) 25 | 26 | expect(log.mock.calls).toMatchSnapshot() 27 | }) 28 | 29 | test('should create organization directory, if it does not exists', async () => { 30 | // if directory does not exists 31 | fs.existsSync.mockReturnValue(false) 32 | // call the function to test 33 | await createJsonFile(repository, organization, results) 34 | expect(fs.promises.mkdir).toHaveBeenCalled() 35 | expect(fs.promises.writeFile).toHaveBeenCalledTimes(1) 36 | }) 37 | 38 | test('should not create organization directory, if it exists', async () => { 39 | /* if directory exists */ 40 | fs.existsSync.mockReturnValue(true) 41 | /* call the function to test */ 42 | await createJsonFile(repository, organization, results) 43 | expect(fs.promises.mkdir).not.toHaveBeenCalled() 44 | expect(fs.promises.writeFile).toHaveBeenCalledTimes(1) 45 | }) 46 | 47 | test('should check if releases exists, when changelog rule fails', async () => { 48 | /* Instead of creating a fixture, having the result inside the test avoids the results to be changed by other tests */ 49 | const failedResults = [ 50 | { 51 | lintResult: { 52 | passed: false, 53 | }, 54 | ruleInfo: { 55 | name: 'Changelog', 56 | }, 57 | }, 58 | ] 59 | await validateChangeLog(failedResults, organization, repository) 60 | expect(failedResults).toMatchObject([{ lintResult: { passed: true }, ruleInfo: { name: 'Changelog' } }]) 61 | }) 62 | 63 | test('should not change changelog rule fails, if releases also do not exists', async () => { 64 | const failedResults = [ 65 | { 66 | lintResult: { 67 | passed: false, 68 | }, 69 | ruleInfo: { 70 | name: 'Changelog', 71 | }, 72 | }, 73 | ] 74 | await validateChangeLog(failedResults, organization, 'repository without releases') 75 | expect(failedResults).toMatchObject([{ lintResult: { passed: false }, ruleInfo: { name: 'Changelog' } }]) 76 | }) 77 | 78 | test('should stop if rule does not exists', async () => { 79 | await validateChangeLog(results, organization, 'repository without releases') 80 | expect(createdInstances[0].repos.listReleases).not.toHaveBeenCalled() 81 | }) 82 | 83 | /* Teardown: clear the mocks and results to avoid false results */ 84 | afterEach(() => { 85 | fs.promises.mkdir.mockClear() 86 | fs.promises.writeFile.mockClear() 87 | createdInstances[0].repos.listReleases.mockClear() 88 | }) 89 | -------------------------------------------------------------------------------- /diagrams/activity.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | title Automated OSS quality check 3 | 4 | (*) --> "Choose a repo to lint" 5 | 6 | if "Is your repo on GitHub?" then 7 | -->[yes] Request(organization, team, repo) 8 | --> CloneInTempDir() 9 | --> Open Local Repository() 10 | else 11 | -->[no] Open Local Repository() 12 | endif 13 | 14 | if "Was your repo found?" then 15 | -left->[yes] Start.lint() 16 | --> [verify .md files] Check.readme() 17 | --> Check.codeOfConduct() 18 | --> Check.contributionGuide() 19 | --> Check.changelog() 20 | --> Check.supportGuide() 21 | --> Check.securityGuide() 22 | --> [verify other files] Check.maintainers 23 | --> Check.license() 24 | --> Check.ifThereIsBinaries() 25 | --> Check.ifThereIsTestEnv() 26 | --> Check.semVer() 27 | 28 | if "Check process finished" then 29 | -->[yes, all passed] Passed outputs 30 | --> console.log("All passed") 31 | --> "Create report src// 32 | ddmmyy-hhmm-reponame.json" 33 | else 34 | -->[no, there are missing files] Failed outputs 35 | --> console.log("All fails") 36 | --> Create.gitHubIssue() 37 | --> "Create report src// 38 | ddmmyy-hhmm-reponame.json" 39 | --> Exit() 40 | -->(*) 41 | endif 42 | else 43 | --> [no] Exit() 44 | endif 45 | @enduml 46 | -------------------------------------------------------------------------------- /frontend/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /frontend/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /frontend/README.md: -------------------------------------------------------------------------------- 1 | # frontend 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /frontend/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /frontend/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # abort on errors 3 | set -e 4 | # build 5 | npm run build 6 | # navigate into the build output directory 7 | cd dist 8 | # if you are deploying to a custom domain 9 | # echo 'www.example.com' > CNAME 10 | 11 | git init 12 | git add -A 13 | git commit -m 'deploy' 14 | git push -f git@github.com:saucelabs/check-my-repo.git master:gh-pages 15 | cd - 16 | -------------------------------------------------------------------------------- /frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint", 9 | "deploy": "sh deploy.sh" 10 | }, 11 | "dependencies": { 12 | "core-js": "^3.8.2", 13 | "register-service-worker": "^1.7.2", 14 | "vue": "^2.6.12", 15 | "vue-router": "3.5.1", 16 | "vuex": "^3.6.0" 17 | }, 18 | "devDependencies": { 19 | "@vue/cli-plugin-babel": "~4.5.10", 20 | "@vue/cli-plugin-eslint": "~4.5.10", 21 | "@vue/cli-plugin-pwa": "~4.5.10", 22 | "@vue/cli-plugin-router": "~4.5.10", 23 | "@vue/cli-plugin-vuex": "~4.5.10", 24 | "@vue/cli-service": "~4.5.10", 25 | "axe-core": "4.2.0", 26 | "babel-eslint": "^10.1.0", 27 | "eslint": "^7.17.0", 28 | "eslint-plugin-vue": "^7.4.1", 29 | "lint-staged": "^10.5.3", 30 | "pug": "^3.0.0", 31 | "pug-plain-loader": "^1.1.0", 32 | "sass": "^1.32.2", 33 | "sass-loader": "^10.1.0", 34 | "vue-axe": "2.4.4", 35 | "vue-template-compiler": "^2.6.12" 36 | }, 37 | "gitHooks": { 38 | "pre-commit": "lint-staged" 39 | }, 40 | "lint-staged": { 41 | "*.{js,jsx,vue}": [ 42 | "vue-cli-service lint", 43 | "git add" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /frontend/public/frontend.json: -------------------------------------------------------------------------------- 1 | [{"repo":"https://github.com/saucelabs","name":"monocle","url":"https://github.com/saucelabs/monocle.git","failed":["Changelog","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"saucerest-java","url":"https://github.com/saucelabs/saucerest-java.git","failed":["Changelog","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"bamboo_sauce","url":"https://github.com/saucelabs/bamboo_sauce.git","failed":["Changelog","License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"ci-sauce","url":"https://github.com/saucelabs/ci-sauce.git","failed":["License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"node-saucelabs","url":"https://github.com/saucelabs/node-saucelabs.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce-java","url":"https://github.com/saucelabs/sauce-java.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"sauce_whisk","url":"https://github.com/saucelabs/sauce_whisk.git","failed":["Contributing","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Code of Conduct"]},{"repo":"https://github.com/saucelabs","name":"the-internet","url":"https://github.com/saucelabs/the-internet.git","failed":["Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"diagnoss","url":"https://github.com/saucelabs/diagnoss.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"appium-getting-started-code-exampes","url":"https://github.com/saucelabs/appium-getting-started-code-exampes.git","failed":["README.md","Test directory","Contributing","Code of Conduct","Security","Support"],"passed":["Changelog","Maintainers email","License","Do not have binaries","Mention"]},{"repo":"https://github.com/saucelabs","name":"vso-sauce-ondemand-plugin","url":"https://github.com/saucelabs/vso-sauce-ondemand-plugin.git","failed":["Changelog","License","Do not have binaries","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Test directory"]},{"repo":"https://github.com/saucelabs","name":"jenkins-sauce-ondemand-plugin","url":"https://github.com/saucelabs/jenkins-sauce-ondemand-plugin.git","failed":["Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"noVNC","url":"https://github.com/saucelabs/noVNC.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"testobject-appium-ruby-api","url":"https://github.com/saucelabs/testobject-appium-ruby-api.git","failed":["Changelog","License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"teamcity-sauce-ondemand-plugin","url":"https://github.com/saucelabs/teamcity-sauce-ondemand-plugin.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"training-test-page","url":"https://github.com/saucelabs/training-test-page.git","failed":["Changelog","License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"foxdriver","url":"https://github.com/saucelabs/foxdriver.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"ios-apps-for-testing","url":"https://github.com/saucelabs/ios-apps-for-testing.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"extended-debugging-demo","url":"https://github.com/saucelabs/extended-debugging-demo.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"oboe.js","url":"https://github.com/saucelabs/oboe.js.git","failed":["Changelog","License","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce-connect-docker","url":"https://github.com/saucelabs/sauce-connect-docker.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sample-app-web","url":"https://github.com/saucelabs/sample-app-web.git","failed":["Changelog","Maintainers email","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"sample-app-mobile","url":"https://github.com/saucelabs/sample-app-mobile.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"CircleCI-SauceLabs-ORB","url":"https://github.com/saucelabs/CircleCI-SauceLabs-ORB.git","failed":["Changelog","License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"runsauce","url":"https://github.com/saucelabs/runsauce.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"dirty-json","url":"https://github.com/saucelabs/dirty-json.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"performance-js-examples","url":"https://github.com/saucelabs/performance-js-examples.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"performance-python-examples","url":"https://github.com/saucelabs/performance-python-examples.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"extended-debugging-Ruby-examples","url":"https://github.com/saucelabs/extended-debugging-Ruby-examples.git","failed":["README.md","Changelog","Test directory","Contributing","Code of Conduct","Security","Support"],"passed":["Maintainers email","License","Do not have binaries","Mention"]},{"repo":"https://github.com/saucelabs","name":"headless-demo-ruby","url":"https://github.com/saucelabs/headless-demo-ruby.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"speedo","url":"https://github.com/saucelabs/speedo.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"performance-CI-demo","url":"https://github.com/saucelabs/performance-CI-demo.git","failed":["Changelog","License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"screener-runner","url":"https://github.com/saucelabs/screener-runner.git","failed":["Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"sauce-elixir","url":"https://github.com/saucelabs/sauce-elixir.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce_bindings","url":"https://github.com/saucelabs/sauce_bindings.git","failed":["Changelog","Security","Support"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Mention"]},{"repo":"https://github.com/saucelabs","name":"simple_sauce_js","url":"https://github.com/saucelabs/simple_sauce_js.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"tracelib","url":"https://github.com/saucelabs/tracelib.git","failed":["Maintainers email","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"performance-samples","url":"https://github.com/saucelabs/performance-samples.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"sauce-connect-action","url":"https://github.com/saucelabs/sauce-connect-action.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"docker-ubuntu1804-ansible","url":"https://github.com/saucelabs/docker-ubuntu1804-ansible.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"1password-teams-open-source","url":"https://github.com/saucelabs/1password-teams-open-source.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Maintainers email","Do not have binaries","Mention"]},{"repo":"https://github.com/saucelabs","name":"network-viewer","url":"https://github.com/saucelabs/network-viewer.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce-connect-launcher","url":"https://github.com/saucelabs/sauce-connect-launcher.git","failed":["License","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Changelog","Maintainers email","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"sauce-puppeteer-runner","url":"https://github.com/saucelabs/sauce-puppeteer-runner.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"testrunner-toolkit","url":"https://github.com/saucelabs/testrunner-toolkit.git","failed":["Changelog","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct"]},{"repo":"https://github.com/saucelabs","name":"saucectl","url":"https://github.com/saucelabs/saucectl.git","failed":[],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Security","Support","Mention"]},{"repo":"https://github.com/saucelabs","name":"homebrew-saucectl","url":"https://github.com/saucelabs/homebrew-saucectl.git","failed":["Changelog","Test directory","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce-playwright-runner","url":"https://github.com/saucelabs/sauce-playwright-runner.git","failed":["Do not have binaries","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"sauce_labs_ranorex","url":"https://github.com/saucelabs/sauce_labs_ranorex.git","failed":["Changelog","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email"]},{"repo":"https://github.com/saucelabs","name":"node-saucectl","url":"https://github.com/saucelabs/node-saucectl.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"salsa_verde","url":"https://github.com/saucelabs/salsa_verde.git","failed":["Changelog","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"saucelabs.github.io","url":"https://github.com/saucelabs/saucelabs.github.io.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"sauce-testcafe-runner","url":"https://github.com/saucelabs/sauce-testcafe-runner.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"logcluster","url":"https://github.com/saucelabs/logcluster.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"sauce-cypress-runner","url":"https://github.com/saucelabs/sauce-cypress-runner.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"new-project","url":"https://github.com/saucelabs/new-project.git","failed":["Changelog","Test directory"],"passed":["README.md","Maintainers email","License","Do not have binaries","Contributing","Code of Conduct","Security","Support","Mention"]},{"repo":"https://github.com/saucelabs","name":".github","url":"https://github.com/saucelabs/.github.git","failed":["README.md","Changelog","License","Test directory","Contributing"],"passed":["Maintainers email","Do not have binaries","Code of Conduct","Security","Support","Mention"]},{"repo":"https://github.com/saucelabs","name":"sauce-docs","url":"https://github.com/saucelabs/sauce-docs.git","failed":["Changelog","Code of Conduct","Security","Support"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Contributing","Mention"]},{"repo":"https://github.com/saucelabs","name":"kafka_exporter","url":"https://github.com/saucelabs/kafka_exporter.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"cascadia-workshop","url":"https://github.com/saucelabs/cascadia-workshop.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"cddl","url":"https://github.com/saucelabs/cddl.git","failed":["Code of Conduct","Security","Support"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing","Mention"]},{"repo":"https://github.com/saucelabs","name":"testcafe-reporter-prometheus-multi","url":"https://github.com/saucelabs/testcafe-reporter-prometheus-multi.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"charts","url":"https://github.com/saucelabs/charts.git","failed":["Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct"]},{"repo":"https://github.com/saucelabs","name":"selenium","url":"https://github.com/saucelabs/selenium.git","failed":["Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"check-my-repo","url":"https://github.com/saucelabs/check-my-repo.git","failed":[],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Security","Support","Mention"]},{"repo":"https://github.com/saucelabs","name":"docusaurus-theme-github-codeblock","url":"https://github.com/saucelabs/docusaurus-theme-github-codeblock.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"repolinter","url":"https://github.com/saucelabs/repolinter.git","failed":["Maintainers email","Mention"],"passed":["README.md","Changelog","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Security","Support"]},{"repo":"https://github.com/saucelabs","name":"screener-storybook","url":"https://github.com/saucelabs/screener-storybook.git","failed":["Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"timeline-viewer","url":"https://github.com/saucelabs/timeline-viewer.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"playwright-test-demo","url":"https://github.com/saucelabs/playwright-test-demo.git","failed":["Changelog","Do not have binaries","Mention"],"passed":["README.md","Maintainers email","License","Test directory","Contributing","Code of Conduct","Security","Support"]},{"repo":"https://github.com/saucelabs","name":"sauce-runners","url":"https://github.com/saucelabs/sauce-runners.git","failed":["Changelog","License","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"zap-api-nodejs","url":"https://github.com/saucelabs/zap-api-nodejs.git","failed":["Test directory","Contributing","Code of Conduct","Security","Support"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Mention"]},{"repo":"https://github.com/saucelabs","name":"saucectl-run-action","url":"https://github.com/saucelabs/saucectl-run-action.git","failed":["License","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"testcafe-browser-provider-ios","url":"https://github.com/saucelabs/testcafe-browser-provider-ios.git","failed":["Support"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing","Code of Conduct","Security","Mention"]},{"repo":"https://github.com/saucelabs","name":"saucectl-run-orb","url":"https://github.com/saucelabs/saucectl-run-orb.git","failed":["Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"sauce-runner-utils","url":"https://github.com/saucelabs/sauce-runner-utils.git","failed":["Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Test directory","Contributing"]},{"repo":"https://github.com/saucelabs","name":"mobilenativefoundation.org","url":"https://github.com/saucelabs/mobilenativefoundation.org.git","failed":["Changelog","Test directory","Contributing","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Code of Conduct"]},{"repo":"https://github.com/saucelabs","name":"py-ccloud","url":"https://github.com/saucelabs/py-ccloud.git","failed":["Test directory","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Contributing"]},{"repo":"https://github.com/saucelabs","name":"saucectl-cypress-example","url":"https://github.com/saucelabs/saucectl-cypress-example.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"saucectl-playwright-example","url":"https://github.com/saucelabs/saucectl-playwright-example.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"saucectl-testcafe-example","url":"https://github.com/saucelabs/saucectl-testcafe-example.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"Selenium_Course_Example_Code","url":"https://github.com/saucelabs/Selenium_Course_Example_Code.git","failed":["README.md","Changelog","License","Contributing","Code of Conduct","Security","Support"],"passed":["Maintainers email","Do not have binaries","Test directory","Mention"]},{"repo":"https://github.com/saucelabs","name":"saucectl-puppeteer-example","url":"https://github.com/saucelabs/saucectl-puppeteer-example.git","failed":["Changelog","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries","Test directory"]},{"repo":"https://github.com/saucelabs","name":"saucelabs-vusb-app","url":"https://github.com/saucelabs/saucelabs-vusb-app.git","failed":["Test directory"],"passed":["README.md","Changelog","Maintainers email","License","Do not have binaries","Contributing","Code of Conduct","Security","Support","Mention"]},{"repo":"https://github.com/saucelabs","name":"saucectl-espresso-example","url":"https://github.com/saucelabs/saucectl-espresso-example.git","failed":["Changelog","Test directory","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Maintainers email","License","Do not have binaries"]},{"repo":"https://github.com/saucelabs","name":"cucumber-android","url":"https://github.com/saucelabs/cucumber-android.git","failed":["License","Contributing","Code of Conduct","Security","Support","Mention"],"passed":["README.md","Changelog","Maintainers email","Do not have binaries","Test directory"]}] -------------------------------------------------------------------------------- /frontend/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | check-my-repo 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /frontend/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twitter/check-my-repo/a1d15edd68e0869ee7231a993a0d1906f9274cc3/frontend/public/logo.png -------------------------------------------------------------------------------- /frontend/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /frontend/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /frontend/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | 112 | -------------------------------------------------------------------------------- /frontend/src/assets/box.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/assets/check-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/assets/external-link.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twitter/check-my-repo/a1d15edd68e0869ee7231a993a0d1906f9274cc3/frontend/src/assets/logo.png -------------------------------------------------------------------------------- /frontend/src/assets/x-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /frontend/src/components/Details.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 49 | 50 | 103 | -------------------------------------------------------------------------------- /frontend/src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 21 | 22 | 50 | -------------------------------------------------------------------------------- /frontend/src/components/Healthy.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 34 | 35 | 76 | -------------------------------------------------------------------------------- /frontend/src/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 23 | 109 | -------------------------------------------------------------------------------- /frontend/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import './registerServiceWorker' 4 | import router from './router' 5 | import store from './store' 6 | 7 | Vue.config.productionTip = false 8 | 9 | if (process.env.NODE_ENV === 'development') { 10 | const VueAxe = require('vue-axe').default 11 | Vue.use(VueAxe, { 12 | auto: true // enable auto check. 13 | }) 14 | } 15 | 16 | new Vue({ 17 | router, 18 | store, 19 | render: h => h(App) 20 | }).$mount('#app') 21 | -------------------------------------------------------------------------------- /frontend/src/registerServiceWorker.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /frontend/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | import About from '../views/About.vue' 5 | import Home from '../views/Home.vue' 6 | import Rules from '../views/Rules.vue' 7 | 8 | Vue.use(VueRouter) 9 | 10 | const routes = [ 11 | { 12 | path: '/', 13 | name: 'Home', 14 | component: Home, 15 | }, 16 | { 17 | path: '/about', 18 | name: 'About', 19 | component: About, 20 | }, 21 | { 22 | path: '/rules', 23 | name: 'Rules', 24 | component: Rules, 25 | }, 26 | ] 27 | 28 | const router = new VueRouter({ 29 | mode: 'history', 30 | base: process.env.BASE_URL, 31 | routes, 32 | linkActiveClass: "active", 33 | linkExactActiveClass: "exact-active", 34 | }) 35 | 36 | export default router 37 | -------------------------------------------------------------------------------- /frontend/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | }, 9 | mutations: { 10 | }, 11 | actions: { 12 | }, 13 | modules: { 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /frontend/src/views/About.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 31 | 32 | 65 | -------------------------------------------------------------------------------- /frontend/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 67 | 68 | 173 | -------------------------------------------------------------------------------- /frontend/src/views/Rules.vue: -------------------------------------------------------------------------------- 1 | 78 | 79 | 85 | 86 | 113 | -------------------------------------------------------------------------------- /frontend/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configureWebpack: { 3 | devtool: 'source-map', 4 | }, 5 | publicPath: process.env.NODE_ENV === 'production' 6 | ? '/check-my-repo/' 7 | : '/' 8 | 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "check-my-repo", 3 | "version": "1.0.0", 4 | "description": "An automated tool built upon Repolinter, that verifies the main necessary parameters to comply with OS best practices", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "test-watch": "jest --coverage --watchAll" 9 | }, 10 | "jest": { 11 | "testPathIgnorePatterns": [ 12 | "__tests__/__fixtures__", 13 | "__tests__/__mocks__", 14 | "__tests__/__snapshots__" 15 | ] 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/saucelabs/check-my-repo" 20 | }, 21 | "keywords": [ 22 | "repolinter", 23 | "automated", 24 | "check", 25 | "quality" 26 | ], 27 | "author": "Paloma Oliveira ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/saucelabs/check-my-repo/issues" 31 | }, 32 | "homepage": "https://github.com/saucelabs/check-my-repo", 33 | "dependencies": { 34 | "@octokit/rest": "18.5.2", 35 | "chalk": "^4.1.0", 36 | "linguist": "^0.1.7", 37 | "rainbow-penguin": "^1.0.3", 38 | "repolinter": "0.11.1", 39 | "rimraf": "^3.0.2", 40 | "simple-git": "2.38.0" 41 | }, 42 | "devDependencies": { 43 | "jest": "26.6.3" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /repolinter.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/todogroup/repolinter/master/rulesets/schema.json", 3 | "extends": "https://raw.githubusercontent.com/twitter/.github/main/repolinter-rulesets/default.yaml" 4 | } 5 | -------------------------------------------------------------------------------- /reports/REPORTS.md: -------------------------------------------------------------------------------- 1 | Those reports, written in JSON file, are meant to be use as a report to analise our reporitories health 2 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { Octokit } = require('@octokit/rest') /* */ 2 | const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }) /*lib for GitHub API */ 3 | const repolinter = require('repolinter') /*project which this is build upon */ 4 | const git = require('simple-git/promise')() /*lib for GitHub API */ 5 | const chalk = require('chalk') 6 | 7 | const repository = process.env.GITHUB_REPOSITORY 8 | 9 | if (repository === null) { 10 | throw 'This GitHub user apparently does not exist'; 11 | } 12 | 13 | const [owner] = repository.split('/') 14 | 15 | const path = require('path') 16 | const fs = require('fs') 17 | const os = require('os') 18 | 19 | const { 20 | printResults, 21 | validateChangeLog, 22 | positiveResults, 23 | negativeResults, 24 | createJsonDashboardFile, 25 | } = require('./utils') 26 | 27 | /* This variable stores the sum of all analised repositories which results are all positives */ 28 | let passingRepositories = 0 29 | 30 | async function main() { 31 | 32 | /* Verifies if it is an organization or a user */ 33 | const { data: { type } } = await octokit.request(`GET /users/${owner}`) 34 | 35 | const ORGANIZATION = 'Organization' 36 | const fetchRepos = type === ORGANIZATION ? octokit.repos.listForOrg : octokit.repos.listForUser 37 | 38 | /* Stores pagination iteration results */ 39 | const results = [] 40 | /* Parameters to call octokit API requests */ 41 | const parameters = { 42 | org: owner, 43 | username: owner, 44 | per_page: 100, 45 | } 46 | 47 | /* This function allows to iterate over all paginations, as explained in documentaton */ 48 | for await (const response of octokit.paginate.iterator(fetchRepos, parameters)) 49 | { 50 | results.push(...response.data) 51 | } 52 | 53 | /* Output is an array of objects to be sent to frontend through frontend.json */ 54 | const output = [] 55 | 56 | for (const d of results) { 57 | const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), `repolinter-${d.name}-`)) 58 | await git.clone(d.clone_url, tmpDir) 59 | const repolinterConnect = await repolinter.lint(tmpDir) /*execute repolinter default ruleset*/ 60 | 61 | /* Validates if Changelog rule passed, of not, search for releases */ 62 | await validateChangeLog(repolinterConnect.results, owner, d.name) 63 | 64 | /* Print in all the results in terminal */ 65 | printResults(d, repolinterConnect.results) 66 | 67 | /* Creates an array to check its length and sum all passing results without a loop */ 68 | const hasFailures = 69 | repolinterConnect.results /* filter messages for what didn't passed */ 70 | .filter(r => !r.lintResult.passed).length > 0 71 | if (!hasFailures) { 72 | passingRepositories++ 73 | } 74 | 75 | /* Push individual repos results to the array which will contain all the results */ 76 | output.push({ 77 | repo: d.owner.html_url, 78 | name: d.name, 79 | url: d.clone_url, 80 | failed: negativeResults(repolinterConnect.results), 81 | passed: positiveResults(repolinterConnect.results), 82 | }) 83 | } 84 | /* Creates one .json file in frontend public folder to make this results available */ 85 | await createJsonDashboardFile(output) 86 | 87 | console.log(chalk(` 88 | 😨 Total repositories with fails = {redBright.bold ${results.length - passingRepositories}} 89 | 😌 Total healthy repositories = {greenBright.bold ${passingRepositories}} 90 | Number of repositories analysed: {cyanBright.bold ${results.length}} 91 | `)) 92 | } 93 | 94 | /* allows to be executed when not used as an imported file */ 95 | if (require.main === module) { 96 | main().then( 97 | () => console.log('Validation successful!'), 98 | err => console.log('Validation failed:', err.stack) 99 | ) 100 | } 101 | 102 | module.exports = main 103 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | // based on repolinter source code https://github.com/todogroup/repolinter/blob/master/bin/repolinter.js 2 | const { Octokit } = require('@octokit/rest') /* */ 3 | const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }) /*lib for GitHub API */ 4 | 5 | const path = require('path') 6 | /** @type {any} */ 7 | const fs = require('fs') 8 | 9 | const repolinter = require('repolinter') /*project which this is build upon */ 10 | 11 | const chalk = require('chalk') 12 | 13 | const formatedDate = new Date().toISOString().substring(0, 13) /*transforms Date() into shorter string*/ 14 | 15 | /* Separate negative and positive results and prints nicely in terminal */ 16 | const printResults = function (data, results, log = console.log) { 17 | const posResults = results /* filter messages for what didn't passed */ 18 | .filter(r => r.lintResult && r.lintResult.passed) 19 | .map(r => repolinter.runRuleset && r.ruleInfo.name) 20 | 21 | const negResults = results /* filter messages for what didn't passed */ 22 | .filter(r => r.lintResult && !r.lintResult.passed) 23 | .map(r => repolinter.runRuleset && r.ruleInfo.name) 24 | 25 | if (results.every(r => r.lintResult && r.lintResult.passed)) { 26 | log(chalk`{bgBlue Repository: ${data.name}\n} 27 | {greenBright Passed all checks 🥳 \n}`) 28 | } else { 29 | log(chalk`{bgBlue Repository: ${data.name}}`) 30 | for (let i = 0; i < negResults.length; i++) { 31 | log(chalk` 32 | {hex('#FF8800') 🚨 ${negResults[i]}}`) 33 | } 34 | for (let i = 0; i < posResults.length; i++) { 35 | log(chalk` 36 | {greenBright ✅ ${posResults[i]}}`) 37 | } 38 | log('\n') 39 | } 40 | } 41 | 42 | /* Filter positive results and make it available to filter data */ 43 | const positiveResults = function (results) { 44 | const posResults = results /* filter messages for what didn't passed */ 45 | .filter(r => r.lintResult && r.lintResult.passed) 46 | .map(r => repolinter.runRuleset && r.ruleInfo.name) 47 | 48 | return posResults 49 | } 50 | 51 | /* Filter negative results and make it available to filter data */ 52 | const negativeResults = function (results) { 53 | const negResults = results 54 | .filter(r => r.lintResult && !r.lintResult.passed) 55 | .map(r => repolinter.runRuleset && r.ruleInfo.name) 56 | 57 | return negResults 58 | 59 | /* In case someone needs an output with ratio */ 60 | /* 61 | return { 62 | results: negResults, 63 | ratio: `${negResults.length} out of ${results.length}`, 64 | } 65 | */ 66 | } 67 | 68 | /* Check if Changelog rule exists, if not, verify if releases exist */ 69 | const validateChangeLog = async function (results, input, repository) { 70 | /* search if the rule exists */ 71 | const changelogResult = results.find(item => item.ruleInfo.name === 'Changelog') 72 | /* if Changelog rule do not exists, or the result has already passed, do not continue */ 73 | if (!changelogResult || changelogResult.lintResult.passed) { 74 | return 75 | } 76 | /* verify if there are releases */ 77 | const releases = await octokit.repos.listReleases({ 78 | owner: input, 79 | repo: repository, 80 | per_page: 100, 81 | }) 82 | /* If releases are found, update Changelog rule result to true */ 83 | const hasReleases = !(releases.data === undefined || releases.data.length === 0) 84 | if (hasReleases) { 85 | /* Observe which data type returns: Objects! */ 86 | changelogResult.lintResult.passed = true 87 | } 88 | } 89 | 90 | /* Creates a JSON file inside a folder with organization name */ 91 | const createJsonFile = async function (repository, input, results) { 92 | const print = await repolinter.jsonFormatter.formatOutput(results) /*JS Object return into json*/ 93 | const directory = path.resolve(__dirname, '..', 'reports', input) 94 | 95 | if (!fs.existsSync(directory)) { 96 | console.log(`A directory is created at ${directory}`) 97 | await fs.promises.mkdir(directory, { recursive: true }) 98 | } 99 | 100 | await fs.promises.writeFile( 101 | path.resolve(directory, `${formatedDate}-${repository}.json`), 102 | JSON.stringify(JSON.parse(print), null, 2) 103 | ) 104 | } 105 | 106 | /* Writes and overwrites a JSON file and save it into frontend/public folder */ 107 | const createJsonDashboardFile = async function (output) { 108 | const directory = path.resolve(__dirname, '..', 'frontend', 'public') 109 | 110 | await fs.promises.writeFile(path.resolve(directory, 'frontend.json'), JSON.stringify(output)) 111 | } 112 | 113 | module.exports = { 114 | formatedDate, 115 | printResults, 116 | positiveResults, 117 | negativeResults, 118 | validateChangeLog, 119 | createJsonFile, 120 | createJsonDashboardFile, 121 | } 122 | --------------------------------------------------------------------------------