script/update-statuses-project.rb (111 lines of code) (raw):

#!/usr/bin/env ruby # Usage: script/update-statuses-project # frozen_string_literal: true require "graphql/client" require "graphql/client/http" statuses = File.read(File.join(File.dirname(__FILE__), "../static/statuses.json")) statuses_json = JSON.parse(statuses) class QueryExecutionError < StandardError; end NOTE_SEPARATOR = " --- " module Github GITHUB_ACCESS_TOKEN = ENV.fetch("GITHUB_TOKEN") URL = "https://api.github.com/graphql" HttpAdapter = GraphQL::Client::HTTP.new(URL) do def headers(_) { "Authorization" => "Bearer #{GITHUB_ACCESS_TOKEN}", "User-Agent" => "Ruby" } end end Schema = GraphQL::Client.load_schema(HttpAdapter) Client = GraphQL::Client.new(schema: Schema, execute: HttpAdapter) end # Project is a GraphQL wrapper for interacting with GitHub projects class Project ProjectQuery = Github::Client.parse <<-'GRAPHQL' query { repository(owner: "primer", name: "view_components") { project(number: 3) { columns(first: 100) { nodes { name id databaseId cards { nodes { id databaseId note column { name } } } } } } } } GRAPHQL CreateCard = Github::Client.parse <<-'GRAPHQL' mutation($note: String!, $projectColumnId: ID!) { addProjectCard(input:{note: $note, projectColumnId: $projectColumnId, clientMutationId: "pvc-actions"}) { __typename } } GRAPHQL MoveCard = Github::Client.parse <<-'GRAPHQL' mutation($cardId: ID!, $columnId: ID!) { moveProjectCard(input:{cardId: $cardId, columnId: $columnId, clientMutationId: "pvc-actions"}) { __typename } } GRAPHQL def self.create_card(note:, column_id:) response = Github::Client.query(CreateCard, variables: { note: note, projectColumnId: column_id }) return unless response.errors.any? raise QueryExecutionError, response.errors[:data].join(", ") end def self.move_card(card_id:, column_id:) response = Github::Client.query(MoveCard, variables: { cardId: card_id, columnId: column_id }) return unless response.errors.any? raise(QueryExecutionError, response.errors[:data].join(", ")) end def self.fetch_columns response = Github::Client.query(ProjectQuery) return response.data.repository.project.columns unless response.errors.any? raise(QueryExecutionError, response.errors[:data].join(", ")) end end columns = Project.fetch_columns.nodes @column_mapping = {} columns.each do |column| @column_mapping[column.name.downcase] = column.id end @cards = columns.map(&:cards).map(&:nodes).flatten def get_card(name_prefix:) @cards.find { |card| card.note.start_with?(name_prefix + NOTE_SEPARATOR) } end def on_correct_column?(card_id:, status:) card = @cards.find { |c| c.id == card_id } card.column.name.casecmp(status).zero? end def move_card(card_id:, status:) column_id = @column_mapping[status.downcase] puts "move card with #{card_id} to #{status} on column #{column_id}" Project.move_card(card_id: card_id, column_id: column_id) end def create_card(component_name:, status:) column_id = @column_mapping[status.downcase] puts "create card with #{component_name} on #{status} on column #{column_id}" Project.create_card(note: component_name + NOTE_SEPARATOR, column_id: column_id) end statuses_json.each do |component_name, component_status| card = get_card(name_prefix: component_name) if card if on_correct_column?(card_id: card.id, status: component_status) puts "#{card.id} is on the right column. noop" else move_card(card_id: card.id, status: component_status) end else create_card(component_name: component_name, status: component_status) end end