├── .gitignore ├── Features_to_add.md ├── README.md ├── csv_issues_to_github.rb ├── docs ├── CODE_STANDARDS.md ├── GOTCHAS.md ├── README.md ├── SECURITY.md ├── api │ └── README.md ├── architecture │ ├── Platform.graffle │ │ ├── data.plist │ │ └── image4.tiff │ └── README.md ├── interaction │ └── README.md ├── source │ └── README.md └── styleguide │ └── README.md ├── github_issues_to_csv.rb ├── product └── README.md └── setup ├── README.md ├── dev ├── README.md ├── linux │ └── README.md ├── mac │ └── README.md └── windows │ └── README.md ├── int └── README.md ├── prod └── README.md ├── stage └── README.md ├── test └── README.md └── uat └── README.md /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/.gitignore -------------------------------------------------------------------------------- /Features_to_add.md: -------------------------------------------------------------------------------- 1 | Features to add 2 | =============== 3 | 4 | ###Priority Items to Add 5 | 6 | 1. GUI: it would be great if this could be an icon on the desktop or in The Dock that a user could click and get a dialogue box with the input fields there. 7 | 2. Password obfuscation: showing the password is really bad. 8 | 3. Key authentication: I don't know if that's an option, but that would negate the need for passwords entirely. 9 | 4. Export each issue's labels as separate fields. 10 | 11 | ###Lower Priority Items (a.k.a. "Wish List") 12 | 13 | 1. Drop-down menus: (stretch goal) it'd be swanky if you ran it and it showed you the ogs and repos you have access to and let you choose that way. 14 | 2. File picker: (stretch goal) it'd be swanky if, when importing, you ran it and it used the standard OSX file picker to choose your CSV file. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Import-issues-to-GitHub-from-CSV 2 | ================================ 3 | 4 | ###Caveat 5 | **You should use two-factor authentication for git**. Unfortunately, 2FA breaks this script and it's beyond my coding/Ruby skills to overcome that. You have been warned. 6 | 7 | ###Abandoned code 8 | At the moment I have no plans to update this code. It did what I needed at the time. To my absolute _amazement_, people who are noticeably better programmers than I have forked this project! If you are hoping to get new features, my best suggestion is that you contact one of the peole who have forked this repo. BTW, there's already a list of features to add, created by the incomparable https://github.com/dnewman108 here: https://github.com/controlgroup/CSV-GitHub-import-export/blob/master/Features_to_add.md 9 | 10 | ###Intro (WTF is this?) 11 | Product Owners and Project Mangers _love_ spreadsheets! They want everything in spreadsheet form. 12 | 13 | If you're using GitHub Issues (and we do) this means that one often needs to move things from GitHub into a spreadsheet ("I need a list of issues to show the client"), or from a spreadsheet into GitHub ("Here is the list of features we are committing to this sprint.") And, personally, I don't like doing things by hand if a computer can do them. And do them better. 14 | 15 | Thus this repo. 16 | 17 | There are two scripts here. One is for importing into GitHub Issues from a CSV file. The other is for getting issues out of GitHub and into a CSV file. 18 | 19 | NOTE: currently, if you have two-factor authentication on, you'll have to turn it off for this to work. Which is a pain and not terribly secure. 20 | 21 | ###Documentation (The stuff you actually care about) 22 | 23 | #####Getting Started 24 | 25 | Make sure you have a GitHub account, that you know your username and password, and that you have access to the repository (repo) that you want to import to, or from which you wish to export. 26 | 27 | You can use the "Clone in Desktop" or "Download Zip" functions on the GitHub page to download the files. If you want to do it using the command line, via ssh, use `git clone git@github.com:controlgroup/CSV-GitHub-import-export.git` 28 | 29 | You will also need to install [octokit](https://github.com/octokit/octokit.rb). 30 | 31 | 32 | 33 | #####Importing issues from a CSV file into GitHub using csv_issues_to_github.rb 34 | 35 | `./csv_issues_to_github.rb` to import issues *into* GitHub from a CSV 36 | 37 | There are two ways to use this. You use it interactively (the default) or you can hard-code your information into the script. If you want to switch, you need to comment out the former and un-comment the latter. 38 | 39 | You will need to provide a CSV file to import. 40 | You will also need to provide it your GitHub username, your GitHub password, the name of your organization, and the name of your repository. If you're working on your own account on not as part of an org, the org is just your GitHub username. 41 | 42 | The CSV file MUST be in the following format: 43 | `title,description,assignee_username,label1,label2,label3` 44 | 45 | You can add more labels or remove labels to it if you wish. However... 46 | 47 | _**Important note**_: all label fields need to be filled. So, if you know you have an issue with only one label, then you need to have only one label field. You do this by removing (or you can add) labels fields at the end of the script. The line for this is marked with a comment (currently it's line 66, but that could change.) 48 | This is a known deficiency that will, with luck, eventually be fixed. 49 | 50 | Fields that have commas in them need to be in double quotes. (Some punctuation doesn't require this, other punctuation may.) 51 | 52 | Either way you use this, you will have to provide your GH password. If you use it interactively, it will show your password on the command line. P-( 53 | 54 | 55 | #####Exporting issues from GitHub to a CSV file using github_issues_to_csv.rb 56 | 57 | `./github_issues_to_csv.rb` to export issues *from* GitHub into a CSV 58 | 59 | This allows you to create a CSV file from issues in a repo. This, too, can be done interactively or not. And it will also show your password if you use it interactively. 60 | 61 | You can also export only a specific milestone if you give it a milestone. If you don't provide a milestone, it will print all issues. 62 | 63 | Note: It will put all labels in one column, without any delimiter. P-( 64 | 65 | 66 | ###Credits (The smart people who did the real work) 67 | It should be noted that I'm not much of a programmer, and I got a tremendous amount of help from [Vik](https://github.com/datvikash) and [Evan](https://github.com/evan108108) 68 | 69 | In addition `github_issues_to_csv` was adapted from the work of others, specifically: https://gist.github.com/henare/1106008 and https://gist.github.com/tkarpinski/2369729 70 | -------------------------------------------------------------------------------- /csv_issues_to_github.rb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/ruby 2 | 3 | # See the README for how to use this. 4 | 5 | require 'rubygems' 6 | require 'octokit' 7 | require 'faraday' 8 | require 'csv' 9 | 10 | # BEGIN INTERACTIVE SECTION 11 | # Comment out this section (from here down to where the end is marked) if you want to use this interactively 12 | 13 | puts "Username:" 14 | username = gets.chomp 15 | if username == "" 16 | abort("You need to supply a username. Thank you, come again.") 17 | end 18 | 19 | puts "Password:" 20 | password = gets.chomp 21 | if password == "" 22 | abort("You need to supply a password. Thank you, come again.") 23 | end 24 | 25 | puts "Path for the CSV file you want to use?" 26 | input_file = gets.chomp 27 | if input_file == "" 28 | abort("You need to supply a CSV file. Thank you, come again.") 29 | end 30 | 31 | puts "Organization?" 32 | org = gets.chomp 33 | if org == "" 34 | abort("You need to supply an organization. Thank you, come again.") 35 | end 36 | 37 | puts "Repository?" 38 | repo = gets.chomp 39 | if repo == "" 40 | abort("You need to supply a repository. Thank you, come again.") 41 | end 42 | 43 | # END INTERACTIVE SECTION 44 | 45 | 46 | # BEGIN HARD-CODED SECTION 47 | # Un-comment out this section (from here down to where the end is marked) if you want to use this without any interaction 48 | # All of these need to be filled out in order for it to work 49 | =begin 50 | input_file = "" 51 | username = "" 52 | password = "" 53 | org = "" 54 | repo = "" 55 | =end # END HARD-CODED SECTION 56 | 57 | org_repo = org + "/" + repo 58 | 59 | client = Octokit::Client.new(:login => username, :password => password) 60 | 61 | csv_text = File.read(input_file) 62 | csv = CSV.parse(csv_text, :headers => true) 63 | 64 | csv.each do |row| 65 | client.create_issue(org_repo, row['title'], row['description'], options = { 66 | :assignee => row['assignee_username'], 67 | :labels => [row['label1'],row['label2'],row['label3']]}) #Add or remove label columns here. 68 | puts "Imported issue: #{row['title']}" 69 | end 70 | 71 | -------------------------------------------------------------------------------- /docs/CODE_STANDARDS.md: -------------------------------------------------------------------------------- 1 | =Whitespace= 2 | 3 | * Use spaces. Set your tab stops to 2-space stops. 4 | * Move new block curlies to a new line. -------------------------------------------------------------------------------- /docs/GOTCHAS.md: -------------------------------------------------------------------------------- 1 | Gotchas 2 | ========= 3 | 4 | The following are things to be aware of when working with this codebase. 5 | 6 | 1. Nothing 7 | 2. Nothing 8 | 3. Nothing 9 | 10 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Docs 2 | ====== 3 | 4 | This directory should be updated in each sprint planning meeting, and will include at least the planned updates for the domain model and UI. 5 | 6 | Each build should add incrementally. This doesn't preclude meta-design artifacts from being included in this directory, but the implementation design should be carved up incrementally and built according to the goals and commitment of the sprint. 7 | 8 | 9 | -------------------------------------------------------------------------------- /docs/SECURITY.md: -------------------------------------------------------------------------------- 1 | Security 2 | ========= 3 | 4 | The security concerns and patterns for this project. 5 | 6 | 7 | Concerns 8 | ========= 9 | 10 | 11 | 12 | Patterns 13 | ========= 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | API Docs 2 | ======== 3 | This folder should include any auto-magic-gen'd or manually-created documentation for your published API. 4 | If the project is a service, include docs describing your interface and protocols here. 5 | 6 | If the project is a library, include header docs. 7 | 8 | -------------------------------------------------------------------------------- /docs/architecture/Platform.graffle/data.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/architecture/Platform.graffle/data.plist -------------------------------------------------------------------------------- /docs/architecture/Platform.graffle/image4.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/architecture/Platform.graffle/image4.tiff -------------------------------------------------------------------------------- /docs/architecture/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/architecture/README.md -------------------------------------------------------------------------------- /docs/interaction/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/interaction/README.md -------------------------------------------------------------------------------- /docs/source/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/source/README.md -------------------------------------------------------------------------------- /docs/styleguide/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/docs/styleguide/README.md -------------------------------------------------------------------------------- /github_issues_to_csv.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require 'octokit' 4 | require 'csv' 5 | require 'date' 6 | 7 | 8 | # BEGIN INTERACTIVE SECTION 9 | # Comment out this section (from here down to where the end is marked) if you want to use this interactively 10 | 11 | puts "Username:" 12 | USERNAME = gets.chomp 13 | if USERNAME == "" 14 | abort("You need to supply a username. Thank you, come again.") 15 | end 16 | 17 | puts "Password:" 18 | PASSWORD = gets.chomp 19 | if PASSWORD == "" 20 | abort("You need to supply a password. Thank you, come again.") 21 | end 22 | 23 | puts "Name of the file you want to create? (.csv will be appended automatically)" 24 | OUTPUT_FILE = gets.chomp 25 | if OUTPUT_FILE == "" 26 | abort("You need to supply a CSV file. Thank you, come again.") 27 | end 28 | 29 | puts "Organization?" 30 | ORG = gets.chomp 31 | if ORG == "" 32 | abort("You need to supply an organization. Thank you, come again.") 33 | end 34 | 35 | puts "Repository?" 36 | REPO = gets.chomp 37 | if REPO == "" 38 | abort("You need to supply a repository. Thank you, come again.") 39 | end 40 | 41 | puts "Do you want just one Milestone? If so, enter it now. Leave this blank to get the entire repo." 42 | TARGET_MILESTONE = gets.chomp 43 | 44 | # END INTERACTIVE SECTION 45 | 46 | 47 | # BEGIN HARD-CODED SECTION 48 | # Un-comment out this section (from here down to where the end is marked) if you want to use this without any interaction 49 | # All of these need to be filled out in order for it to work 50 | =begin 51 | OUTPUT_FILE = "" 52 | USERNAME = "" # Put your GitHub username inside the quotes 53 | PASSWORD = "" # Put your GitHub password inside the quotes 54 | ORG = "" # Put your organization (or username if you have no org) name here 55 | REPO = "" # Put the repository name here 56 | # Want to only get a single milestone? Put the milestone name in here: 57 | TARGET_MILESTONE="" # keep this equal to "" if you want all milestones 58 | =end # END HARD-CODED SECTION 59 | 60 | 61 | # Your local timezone offset to convert times 62 | TIMEZONE_OFFSET="-4" 63 | 64 | client = Octokit::Client.new(:login => USERNAME, :password => PASSWORD) 65 | 66 | csv = CSV.new(File.open(File.dirname(__FILE__) + "/" + OUTPUT_FILE + ".csv", 'w')) 67 | 68 | puts "Initialising CSV file..." 69 | #CSV Headers 70 | header = [ 71 | "Issue number", 72 | "Title", 73 | "Description", 74 | "Date created", 75 | "Date modified", 76 | "Labels", 77 | "Milestone", 78 | "Status", 79 | "Assignee", 80 | "Reporter" 81 | ] 82 | 83 | csv << header 84 | 85 | puts "Getting issues from Github..." 86 | temp_issues = [] 87 | issues = [] 88 | page = 0 89 | begin 90 | page = page +1 91 | temp_issues = client.list_issues("#{ORG}/#{REPO}", :state => "closed", :page => page) 92 | issues = issues + temp_issues; 93 | end while not temp_issues.empty? 94 | temp_issues = [] 95 | page = 0 96 | begin 97 | page = page +1 98 | temp_issues = client.list_issues("#{ORG}/#{REPO}", :state => "open", :page => page) 99 | issues = issues + temp_issues; 100 | end while not temp_issues.empty? 101 | 102 | puts "Processing #{issues.size} issues..." 103 | issues.each do |issue| 104 | 105 | labels = "" 106 | label = issue['labels'] || "None" 107 | if (label != "None") 108 | label.each do |item| 109 | labels += item['name'] + " " 110 | end 111 | end 112 | 113 | assignee = "" 114 | assignee = issue['assignee'] || "None" 115 | if (assignee != "None") 116 | assignee = assignee['login'] 117 | end 118 | 119 | milestone = issue['milestone'] || "None" 120 | if (milestone != "None") 121 | milestone = milestone['title'] 122 | end 123 | 124 | if ((TARGET_MILESTONE == "") || (milestone == TARGET_MILESTONE)) 125 | # Needs to match the header order above, date format are based on Jira default 126 | row = [ 127 | issue['number'], 128 | issue['title'], 129 | issue['body'], 130 | DateTime.parse(issue['created_at'].to_s).new_offset(TIMEZONE_OFFSET).strftime("%d/%b/%y %l:%M %p"), 131 | DateTime.parse(issue['updated_at'].to_s).new_offset(TIMEZONE_OFFSET).strftime("%d/%b/%y %l:%M %p"), 132 | labels, 133 | milestone, 134 | issue['state'], 135 | assignee, 136 | issue['user']['login'] 137 | ] 138 | csv << row 139 | end 140 | end 141 | 142 | puts "Done!" 143 | -------------------------------------------------------------------------------- /product/README.md: -------------------------------------------------------------------------------- 1 | Product 2 | ======== 3 | 4 | This directory is where your product should live. Treat this as the repo root from an application point of view. 5 | 6 | For Yii projects, this would be the location for: 7 | 8 | * product 9 | * yii 10 | * webapp 11 | * devops 12 | 13 | For Cinder projects, this would be the location for: 14 | 15 | * product 16 | * include 17 | * resources 18 | * src 19 | * vc10 20 | * xcode 21 | 22 | For Akka projects: 23 | 24 | * product 25 | * project 26 | * src 27 | * main 28 | * test 29 | 30 | Etc, and so on, and so on. 31 | -------------------------------------------------------------------------------- /setup/README.md: -------------------------------------------------------------------------------- 1 | Environments 2 | ============= 3 | 4 | This directory should house build tools for environments. Use puppet, homebrew, etc, in the appropriate shell file to build out everything needed for this project on the given platform. 5 | 6 | If manual instructions exist in addition to build tools (for things that cannot be scripted, such as hardware integration or software purchases), use this file for instructions. 7 | 8 | 9 | Manual Instructions 10 | ==================== 11 | 12 | None, unless someone edits this. -------------------------------------------------------------------------------- /setup/dev/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/dev/README.md -------------------------------------------------------------------------------- /setup/dev/linux/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/dev/linux/README.md -------------------------------------------------------------------------------- /setup/dev/mac/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/dev/mac/README.md -------------------------------------------------------------------------------- /setup/dev/windows/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/dev/windows/README.md -------------------------------------------------------------------------------- /setup/int/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/int/README.md -------------------------------------------------------------------------------- /setup/prod/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/prod/README.md -------------------------------------------------------------------------------- /setup/stage/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/stage/README.md -------------------------------------------------------------------------------- /setup/test/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/test/README.md -------------------------------------------------------------------------------- /setup/uat/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Intersection/cg-CSV-GitHub-import-export/4ba822721d6177989ae182776d8f5e8bc3baba4b/setup/uat/README.md --------------------------------------------------------------------------------