name: Validating the list of maintainers

on:
  pull_request:
    types: [opened, reopened, synchronize, ready_for_review]
    paths:
      - 'MAINTAINERS.yaml'

jobs:
  # Make sure that changes in the MAINTAINERS.yaml file do not break the schema
  # Until we have MAINTAINERS.yaml updates automated, we need to ensure we are not breaking things
  validate_schema:
    if: github.event.pull_request.draft == false
    name: Validate JSON Schema for MAINTAINERS list
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - run: npm install ajv@6.12.6
      - name: Install dependencies
        run: npm install js-yaml@4.1.0
      - name: Validate list with schema
        uses: actions/github-script@v4
        with:
          script: |
            const Ajv = require("ajv");
            const fs = require('fs').promises;
            const yaml = require('js-yaml');

            const schema = await fs.readFile('.github/workflows/tsc_members_validator/schema.json', 'utf8');
            const members = await fs.readFile('MAINTAINERS.yaml', 'utf8');
            
            const ajv = new Ajv();
            const validator = ajv.compile(JSON.parse(schema));

            const valid = validator(yaml.load(members));

            if (!valid) {
              core.error(`Validation of maintainers file failed with the following errors:`);
              core.error(validator.errors);
            } else {
              core.info(`MAINTAINERS file is valid`);
            }

  # Open governance model doesn't allow more than 1/4 maintainers affiliated with a single company
  calculate_companies:
    if: github.event.pull_request.draft == false
    name: Calculate TSC members affiliation
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Install dependencies
        run: npm install js-yaml@4.1.0
      - name: Calculate
        uses: actions/github-script@v4
        with:
          script: |
            const fs = require('fs');
            const yaml = require('js-yaml');
            const members = yaml.load(fs.readFileSync('./MAINTAINERS.yaml', 'utf8'));
            // Filter in the members who are part of the TSC
            const tscMembers = members.filter(member => member.isTscMember);

            const allTscMembers = tscMembers.length;

            const allowedMemberPerCompany = Math.floor(allTscMembers / 4);
            const numberOfMemByCompany = tscMembers.reduce((acc, m) => {
              const company = m.company && m.company.toLowerCase();
              if (company) acc.has(company) ? acc.set(company, acc.get(company) + 1) : acc.set(company, 1);
              return acc;
            }, new Map());

            numberOfMemByCompany.forEach((numberOfRepresentatives, companyName) => {
              if (numberOfRepresentatives > allowedMemberPerCompany) {
                core.setFailed(`There are too many TSC members affiliated with ${companyName} and it violates the open governance model. ${numberOfRepresentatives} is more than 1/4 of ${allTscMembers}`);
              }
            });