Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add govuk repo tags check #561

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/verify_repo_tags.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
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": "#govuk-platform-support",
"username": "Platform Alerts",
"text": "The <https://github.com/alphagov/govuk-developer-docs/blob/main/data/repos.yml|Developer Docs repo list> is out of sync with the repos tagged as 'govuk' in GitHub.",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "The <https://github.com/alphagov/govuk-developer-docs/blob/main/data/repos.yml|Developer Docs repo list> 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 }}
20 changes: 20 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require_relative "lib/validate_repos"

begin
require "rspec/core/rake_task"

Expand Down Expand Up @@ -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
Expand Down
46 changes: 46 additions & 0 deletions lib/validate_repos.rb
Original file line number Diff line number Diff line change
@@ -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) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original FetchRepos class was used by both repo tags check and a script that configured GitHub. The exclusion of ignored_repos in the original code was used only by GitHub configuration script. The original govuk repo tags check didn't have ignore list.

We still want to be notified if licensify doesn't have govuk tag or if it's removed from the repos.json but still tagged.

I think we can ignore them for now, as there are some other considerations related to the "Deploy out of sync" alerting, which don't appear to be addressed.

.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
71 changes: 71 additions & 0 deletions spec/validate_repos_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
require "spec_helper"
require_relative "../lib/validate_repos"

RSpec.describe ValidateRepos do
before do
@repo_mock = double("Repo", topics: %w[govuk], archived: false, full_name: "this-is-a-govuk-repo")
allow(@repo_mock).to receive(:[]).with("name").and_return("this-is-a-govuk-repo")
allow(@repo_mock).to receive(:[]).with(:full_name).and_return("this-is-a-govuk-repo")
allow(ENV).to receive(:fetch).with("GITHUB_TOKEN").and_return("dummy_token")
allow_any_instance_of(Octokit::Client).to receive(:org_repos).and_return([@repo_mock])
end

it "should ignore any repos that exist in repos.json AND are tagged govuk in GitHub" do
repos = [{
"app_name" => "this-is-a-govuk-repo",
}]

stub_repos_json(repos)

validator = ValidateRepos.new

expect(validator.untagged_repos).to eq("")
expect(validator.falsely_tagged_repos).to eq("")
end

it "doesn't say that a repo is missing the govuk tag if it has been added to the ignore list" do
app_name = "this-is-a-govuk-repo"
allow_any_instance_of(ValidateRepos).to receive(:ignored_repos).and_return(["alphagov/#{app_name}"])

repos = [{
"app_name" => app_name,
}]

stub_repos_json(repos)

validator = ValidateRepos.new

expect(validator.untagged_repos).to eq("")
expect(validator.falsely_tagged_repos).to eq("")
end

it "should alert if it finds an untagged repo in repos.json" do
repos = [
{ "app_name" => "this-is-a-govuk-repo" },
{ "app_name" => "this-govuk-repo-is-not-tagged!" },
]

stub_repos_json(repos)

validator = ValidateRepos.new

expect(validator.untagged_repos).to eq("this-govuk-repo-is-not-tagged!")
expect(validator.falsely_tagged_repos).to eq("")
end

it "should alert if it finds a repo that has falsely been tagged as govuk." do
repos = []

stub_repos_json(repos)

validator = ValidateRepos.new

expect(validator.falsely_tagged_repos).to eq("this-is-a-govuk-repo")
expect(validator.untagged_repos).to eq("")
end

def stub_repos_json(repos)
stub_request(:get, "https://docs.publishing.service.gov.uk/repos.json")
.to_return(status: 200, body: repos.to_json, headers: {})
end
end