diff --git a/.github/workflows/verify_repo_tags.yml b/.github/workflows/verify_repo_tags.yml new file mode 100644 index 00000000..ed5a17de --- /dev/null +++ b/.github/workflows/verify_repo_tags.yml @@ -0,0 +1,62 @@ +name: "Verify Repo Tags" + +on: + workflow_dispatch: {} + schedule: + - cron: '00 10 * * 1-5' # Runs at 10:00 UTC, Monday through Friday. + +jobs: + verify-repo-tags: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true + + - name: Verify Repo Tags + id: verify_repo_tags + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + run: | + EXIT_CODE=0 + output=$(bundle exec rake verify_repo_tags) || EXIT_CODE=$? + + echo "$output" + + exit $EXIT_CODE + + - name: Notify failure + uses: slackapi/slack-github-action@v1 + if: ${{ failure() }} + with: + payload: | + { + "channel": "#murilo-testing", + "username": "Platform Alerts", + "text": "The is out of sync with the repos tagged as 'govuk' in GitHub.", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "The is out of sync with the repos tagged as 'govuk' in GitHub." + }, + "accessory": { + "type": "button", + "text": { + "type": "plain_text", + "text": "Check the build logs for details" + }, + "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "action_id": "button-view-workflow" + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/Rakefile b/Rakefile index ebad37e0..fd087ccd 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +require_relative "lib/validate_repos" + begin require "rspec/core/rake_task" @@ -25,6 +27,24 @@ rescue LoadError # no rubocop available end +desc "Verify that GOVUK repos are tagged #govuk" +task :verify_repo_tags do + validator = ValidateRepos.new + + untagged_message = <<~UNTAGGED + The following repos in the repos.yml file in govuk-developer-docs do not have the govuk tag on GitHub: + UNTAGGED + + falsely_tagged_message = <<~FALSETAG + The following repos have the govuk tag on GitHub but are not in the repos.yml file in govuk-developer-docs: + FALSETAG + + puts "#{untagged_message}\n#{validator.untagged_repos}" unless validator.untagged_repos.empty? + puts "#{falsely_tagged_message}\n#{validator.falsely_tagged_repos}" unless validator.falsely_tagged_repos.empty? + + exit 1 unless validator.untagged_repos.empty? && validator.falsely_tagged_repos.empty? +end + task default: %i[ jsonlint rubocop diff --git a/lib/validate_repos.rb b/lib/validate_repos.rb new file mode 100644 index 00000000..f1464873 --- /dev/null +++ b/lib/validate_repos.rb @@ -0,0 +1,46 @@ +require "json" +require "octokit" +require "open-uri" +require "yaml" + +class ValidateRepos + def initialize + Octokit.auto_paginate = true + @client = Octokit::Client.new(access_token: ENV.fetch("GITHUB_TOKEN")) + end + + def github_repos_tagged_govuk + @github_repos_tagged_govuk ||= repos.map { |repo| repo["name"] } + end + + def govuk_repo_names + @govuk_repo_names ||= JSON.parse(Net::HTTP.get_response(URI.parse("https://docs.publishing.service.gov.uk/repos.json")).body) + .map { |repo| repo["app_name"] } + .reject { |app| ignored_apps.include?(app) } + end + + def untagged_repos + (govuk_repo_names - github_repos_tagged_govuk).join("\n") + end + + def falsely_tagged_repos + (github_repos_tagged_govuk - govuk_repo_names).join("\n") + end + + def repos + @client + .org_repos("alphagov", accept: "application/vnd.github.mercy-preview+json") + .select { |repo| repo.topics.to_a.include?("govuk") } + .reject(&:archived) + .reject { |repo| ignored_repos.include?(repo.full_name) } + .sort_by { |repo| repo[:full_name] } + end + + def ignored_repos + ["alphagov/licensify"] # Licensify consists of 3 apps in 1 repo + end + + def ignored_apps + %w[licensify-backend] + end +end