Module: ActiveProject::Adapters::GithubProject::Projects

Includes:
Helpers
Included in:
ActiveProject::Adapters::GithubProjectAdapter
Defined in:
lib/active_project/adapters/github_project/projects.rb

Instance Method Summary collapse

Methods included from Helpers

#fetch_all_pages, #map_user, #owner_node_id, #project_field_ids

Instance Method Details

#create_project(attributes) ⇒ Object

Create a shiny new GitHub Project.

Required:

- :name 

Step 1: create project. Step 2: tweet “Just shipped something huge 🔥 #buildinpublic”. Step 3: forget about it.



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/active_project/adapters/github_project/projects.rb', line 94

def create_project(attributes)
  name = attributes[:name] or raise ArgumentError, "Missing :name"
  owner_id = owner_node_id(@config.owner)
  q = "    mutation($name:String!, $owner:ID!){\n      createProjectV2(input:{title:$name,ownerId:$owner}) { projectV2 { id number title } }\n    }\n  GQL\n  proj = request_gql(query: q, variables: { name: name, owner: owner_id })\n         .dig(\"createProjectV2\", \"projectV2\")\n  build_project_resource(proj)\nend\n"

#delete_project(project_id) ⇒ Object

Soft-delete a project by “closing” it.

GitHub doesn’t believe in real deletion yet, only ghosting. Just like that app idea you posted about but never launched.



113
114
115
116
117
118
119
# File 'lib/active_project/adapters/github_project/projects.rb', line 113

def delete_project(project_id)
  q = "    mutation($id:ID!){ updateProjectV2(input:{projectId:$id, closed:true}) { clientMutationId } }\n  GQL\n  request_gql(query: q, variables: { id: project_id })\n  true\nend\n"

#find_project(id_or_number) ⇒ Object

Find a project either by its public-facing number or internal node ID.

Supports both:

- people who proudly know their project number (respect)
- and people copy-pasting weird node IDs at 2am on a Saturday.


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/active_project/adapters/github_project/projects.rb', line 60

def find_project(id_or_number)
  if id_or_number.to_s =~ /^\d+$/
    # UI-visible number path: the civilized way.
    owner = @config.owner
    num = id_or_number.to_i
    q = "      query($login: String!, $num: Int!) {\n        user(login: $login) {\n          projectV2(number: $num) { id number title }\n        }\n      }\n    GQL\n    data = request_gql(query: q, variables: { login: owner, num: num })\n    proj = data.dig(\"user\", \"projectV2\") or raise NotFoundError\n  else\n    # Node ID path: the \"I swear I know what I'm doing\" path.\n    proj = request_gql(\n      query: \"query($id:ID!){ node(id:$id){ ... on ProjectV2 { id number title }}}\",\n      variables: { id: id_or_number }\n    )[\"node\"]\n  end\n  build_project_resource(proj)\nend\n"

#list_projects(options = {}) ⇒ Object

List all ProjectsV2 for a GitHub user.

Because nothing says “weekend hustle” like spinning up yet another project, posting “🚀 Day 1 of #BuildInPublic” on X, and immediately abandoning it by Tuesday.



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
# File 'lib/active_project/adapters/github_project/projects.rb', line 15

def list_projects(options = {})
  owner     = options[:owner] || @config.owner
  page_size = options.fetch(:page_size, 50)

  # ---- build query template ------------------------------------------------
  query_tmpl = lambda { |kind|
    # rubocop:disable Layout/LineLength
    "      query($login:String!, $first:Int!, $after:String){\n        \#{kind}(login:$login){\n          projectsV2(first:$first, after:$after){\n            nodes{ id number title }\n            pageInfo{ hasNextPage endCursor }\n          }\n        }\n      }\n    GQL\n    # rubocop:enable Layout/LineLength\n  }\n\n  # ---- fetch pages, trying user first, then organisation -------------------\n  begin\n    nodes = fetch_all_pages(\n      query_tmpl.call(\"user\"),\n      variables: { login: owner, first: page_size },\n      connection_path: %w[user projectsV2]\n    )\n  rescue ActiveProject::NotFoundError, ActiveProject::ValidationError\n    nodes = fetch_all_pages(\n      query_tmpl.call(\"organization\"),\n      variables: { login: owner, first: page_size },\n      connection_path: %w[organization projectsV2]\n    )\n  end\n\n  nodes.map { |proj| build_project_resource(proj) }\nend\n"