Skip to content

CLI to create GitHub Issues from GitHub Discussions

License

Notifications You must be signed in to change notification settings

suzuki-shunsuke/ghd2i

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

58 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ghd2i - GitHub Discussions to Issues

MIT | Install | Usage

ghd2i is a CLI to create GitHub Issues from GitHub Discussions. This is useful when you want to convert discussions to issues.

ghd2i run [<discussion url> ...]

Examples

Left: Original Discussion | Right: Created Issue

image

--

image

GitHub Access Token

ghd2i requires a GitHub Access Token to get discussions and create and edit issues. Please set the environment variable GITHUB_TOKEN.

Search Discussions

You can search Discussions using -query option. is:discussions is added to the query.

ghd2i run -query "repo:suzuki-shunsuke/test-ghd2i is:open"

Output data

By default, ghd2i run command gets discussion data via GitHub API. You can dump the data to a data file by ghd2i get-discussion command and pass it to ghd2i run command. This is useful when you customize and test templates.

# Dump data to a data file
ghd2i get-discussion <discussion url> [<discussion url> ...] > discussion.json
# Pass the data file
ghd2i run -data discussion.json

-query is also available.

ghd2i get-discussion -query "repo:suzuki-shunsuke/test-ghd2i is:open" > discussions.json

Data Format

Example data
{
  "Discussions": [
    {
      "ID": "D_kwDODTmpTc4APQPc",
      "Title": "test",
      "Body": "test discussion",
      "URL": "https://github.com/suzuki-shunsuke/test-github-action/discussions/54",
      "ClosedAt": "2024-12-02T22:44:10Z",
      "CreatedAt": "2022-04-10T01:15:58Z",
      "UpdatedAt": "2024-12-02T22:44:27Z",
      "AnswerChosenAt": "2022-04-10T01:24:57Z",
      "UpvoteCount": 1,
      "Repo": {
        "Owner": "suzuki-shunsuke",
        "Name": "test-github-action"
      },
      "Author": {
        "Login": "suzuki-shunsuke",
        "AvatarURL": "https://avatars.githubusercontent.com/u/13323303?u=afedf0091bfd70a6a79c55f6aca781c94cb862f7\u0026v=4"
      },
      "Category": {
        "Name": "Q\u0026A",
        "Emoji": ":pray:"
      },
      "Comments": [
        {
          "ID": "DC_kwDODTmpTc4AJrky",
          "Body": "test comment",
          "URL": "https://github.com/suzuki-shunsuke/test-github-action/discussions/54#discussioncomment-2537778",
          "Author": {
            "Login": "suzuki-shunsuke",
            "AvatarURL": "https://avatars.githubusercontent.com/u/13323303?u=afedf0091bfd70a6a79c55f6aca781c94cb862f7\u0026v=4"
          },
          "CreatedAt": "2022-04-10T01:19:33Z",
          "Reactions": {
            "πŸ‘": {
              "Emoji": "πŸ‘",
              "Count": 1
            },
            "πŸ˜•": {
              "Emoji": "πŸ˜•",
              "Count": 1
            }
          },
          "Replies": [
            {
              "ID": "DC_kwDODTmpTc4AJrk2",
              "Body": "test reply",
              "URL": "https://github.com/suzuki-shunsuke/test-github-action/discussions/54#discussioncomment-2537782",
              "UpvoteCount": 0,
              "Reactions": {},
              "Author": {
                "Login": "suzuki-shunsuke",
                "AvatarURL": "https://avatars.githubusercontent.com/u/13323303?u=afedf0091bfd70a6a79c55f6aca781c94cb862f7\u0026v=4"
              },
              "CreatedAt": "2022-04-10T01:21:03Z",
              "IsAnswer": false,
              "IsMinimized": false
            }
          ],
          "UpvoteCount": 1,
          "IsAnswer": true,
          "IsMinimized": false
        },
        {
          "ID": "DC_kwDODTmpTc4AJtD_",
          "Body": "test comment 2",
          "URL": "https://github.com/suzuki-shunsuke/test-github-action/discussions/54#discussioncomment-2543871",
          "Author": {
            "Login": "suzuki-shunsuke",
            "AvatarURL": "https://avatars.githubusercontent.com/u/13323303?u=afedf0091bfd70a6a79c55f6aca781c94cb862f7\u0026v=4"
          },
          "CreatedAt": "2022-04-11T11:07:27Z",
          "Reactions": {},
          "Replies": [],
          "UpvoteCount": 1,
          "IsAnswer": false,
          "IsMinimized": false
        }
      ],
      "Labels": [
        "foo",
        "aws/terraform-ci"
      ],
      "Answer": {
        "ID": "DC_kwDODTmpTc4AJrky",
        "Body": "test comment",
        "CreatedAt": "2022-04-10T01:19:33Z",
        "UpvoteCount": 1,
        "Author": {
          "Login": "suzuki-shunsuke",
          "AvatarURL": "https://avatars.githubusercontent.com/u/13323303?u=afedf0091bfd70a6a79c55f6aca781c94cb862f7\u0026v=4"
        },
        "Reactions": {
          "πŸ‘": {
            "Emoji": "πŸ‘",
            "Count": 1
          },
          "πŸ˜•": {
            "Emoji": "πŸ˜•",
            "Count": 1
          }
        }
      },
      "Reactions": {},
      "Locked": true,
      "Closed": true
    }
  ]
}

Customize templates

You can customize templates of issue body and issue comments.

Create a configuration file:

ghd2i create-config

Please edit the generated configuration file as you like.

Before creating issues, you can test the configuration by -dry-run option:

ghd2i run -dry-run [-data <data file>] [<discussion url> ...]

Configuration file

Configuration file is optional. By default, if a file \.ghd2i.yaml exists, it's used as a configuration file. You can also specify the configuration file by -config option.

ghd2i run -config config.yaml <discussion url>

Templates are parsed using Go's text/template.

title: A template of issue title. This is parsed using Go's text/template.
issue_template: |
  A template of issue body.
  This is parsed using Go's text/template.
comment_template: |+
  A template of issue comments.
  This is parsed using Go's text/template.

Each discussion in data is passed to title and issue_template. Each discussion comment in data is passed to comment_template.

Close and Lock created Issues

By default, ghd2i closes issues if discussions are closed. And it locks issues if discussion are locked. You can change this behaviour using -lock and -close option. These options accept the following values.

  • auto (default): closes and locks issues if discussions are closed and locks
  • always: closes and locks issues definitely
  • never: never closes and locks issues

e.g.

ghd2i run -lock never -close always <discussion url>

Close and lock and post a comment to Discussions

After creating issues, ghd2i can close and lock and post a comment to Discussions.

To close and lock discussion, you can use -lock-discussion and -close-discussion options.

ghd2i run -lock-discussion -close-discussion

To post a comment to discussions, you need a configuration file.

discussion_comment_template: |
  This discussion is closed and locked because we migrate Discussions to Issues.
  {{.Issue.URL}}

Add labels and assignees

You can use -label (-l) and -assignee (-a) options.

ghd2i run -l foo -l bar -a suzuki-shunsuke -a octokit -query "repo:suzuki-shunsuke/test-ghd2i is:open"

Q. Why not using GitHub's native feature Create issue from discussion?

GitHub provides a Web UI to create an issue from a discussion.

image

But this feature doesn't create issue comments from discussion comments and replies.

So we've developed ghd2i.

LICENSE

MIT

About

CLI to create GitHub Issues from GitHub Discussions

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •