exclude: true --- class: title_bg .title[ ghclass ] .subtitle[ an R package for managing classes with GitHub ] .conference[ .name[ UseR!2019 · Toulouse ] .bitly[ [bit.ly/User2019_ghclass](http://bit.ly/User2019_ghclass) ] ] .author[ .name[ Colin Rundel ] .school[ Univ of Edinburgh · Duke Univ ] ] --- background-image: url("imgs/workflow.001.jpeg") background-position: center background-size: contain --- background-image: url("imgs/workflow.002.jpeg") background-position: center background-size: contain --- background-image: url("imgs/workflow.003.jpeg") background-position: center background-size: contain --- background-image: url("imgs/github_org.jpeg") background-position: center background-size: contain --- ## Setup 1. Signup for a GitHub Account - [github.com]() 2. Setup git and get a GitHub personal access token (PAT) - [github.com/settings/tokens](https://github.com/settings/tokens) - Need help? Read [usethis setup vignette](https://usethis.r-lib.org/articles/articles/usethis-setup.html) or [happy git with R](https://happygitwithr.com/) 3. Signup for the GitHub Education Discount - [education.github.com/benefits](https://education.github.com/benefits) 4. Create a GitHub Organization for your class - [github.com/organizations/new](https://github.com/organizations/new) <br/> .center[ Only step 4 needs to be repeated for a new class! ] --- ## Introduction to `ghclass` ```r remotes::install_github("rundel/ghclass") library(ghclass) ``` -- <br/> Some design principals behind this package: 1. All of the package's functions are prefixed with either `org`, `repo`, `team`, `github` or `local_repo` to indicate what they operate on. 2. Most functions are vectorized over their parameters, to allow related operations to be grouped. 3. All messaging is built on `usethis::ui_`* functions, as such you can make it shutup with `options(usethis.quiet = TRUE)`. 4. Most actions are non-destructive and/or backed by git, the handful of dangerous operations will warn you. 5. Follow the unix design philosophy when possible, work towards simple & composable functions --- ## Org & Roster Today we will be using [ghclass-demo](https://github.com/ghclass-demo) as our example, hopefully your Org has a slightly more informative name . -- .center[ (I find `course#`-`semster` works well, e.g. `Sta323-Sp19`). ] -- <br/><br/> ```r (roster = readr::read_csv("files/roster.csv")) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #949494;'># A tibble: 6 x 5</span><span> ## uid email github hw01 hw02 ## </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> ## </span><span style='color: #BCBCBC;'>1</span><span> za17 anya@school.edu ghclass-anya hw01-team01 hw02-team01 ## </span><span style='color: #BCBCBC;'>2</span><span> kb34 bruno@school.edu ghclass-bruno hw01-team02 hw02-team02 ## </span><span style='color: #BCBCBC;'>3</span><span> ac13 celine@school.edu ghclass-celine hw01-team03 hw02-team03 ## </span><span style='color: #BCBCBC;'>4</span><span> bd88 diego@school.edu ghclass-diego hw01-team01 hw02-team03 ## </span><span style='color: #BCBCBC;'>5</span><span> se01 elijah@school.edu ghclass-elijah hw01-team02 hw02-team01 ## </span><span style='color: #BCBCBC;'>6</span><span> df00 francis@school.edu ghclass-francis hw01-team03 hw02-team02 </span></CODE></PRE> --- background-image: url("imgs/01_github_empty.png") background-position: center background-size: contain --- ## Checking your git config ```r usethis::git_sitrep() ``` <PRE class="fansi fansi-output"><CODE>## <span style='font-weight: bold;'>Git user</span><span> ## * Name: </span><span style='color: #0000BB;'>'Colin Rundel'</span><span> ## * Email: </span><span style='color: #0000BB;'>'rundel@gmail.com'</span><span> ## * Vaccinated: </span><span style='color: #0000BB;'>TRUE</span><span> ## </span><span style='font-weight: bold;'>usethis + git2r</span><span> ## * Default usethis protocol: </span><span style='color: #555555;'><unset></span><span> ## * git2r supports SSH: </span><span style='color: #0000BB;'>TRUE</span><span> ## * Credentials: </span><span style='color: #0000BB;'>'<usethis + git2r default behaviour>'</span><span> ## </span><span style='font-weight: bold;'>GitHub</span><span> ## * Personal access token: </span><span style='color: #0000BB;'>'<found in env var>'</span><span> ## * User: </span><span style='color: #0000BB;'>'rundel'</span><span> ## * Name: </span><span style='color: #0000BB;'>'Colin Rundel'</span><span> ## </span><span style='font-weight: bold;'>Repo</span><span> ## * Path: </span><span style='color: #0000BB;'>'/Users/rundel/Desktop/Presentations/.git'</span><span> ## * Local branch -> remote tracking branch: </span><span style='color: #0000BB;'>'master'</span><span> -> </span><span style='color: #0000BB;'>'origin/master'</span><span> ## </span><span style='font-weight: bold;'>GitHub pull request readiness</span><span> ## * origin: </span><span style='color: #0000BB;'>rundel/Presentations</span><span>, </span><span style='color: #0000BB;'>can push</span><span> ## * upstream: </span><span style='color: #0000BB;'>'<no such remote>'</span><span> </span></CODE></PRE> --- ## Checking your git config - `ghclass` ```r github_test_token() ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Your github token is functioning correctly. </span></CODE></PRE> -- ```r github_test_token("bad token") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #BB0000;'>✖</span><span> Your github token failed to authenticate. ## [Error: GitHub API error (401): 401 Unauthorized] </span></CODE></PRE> --- ## Inviting Students ```r org_invite(org = "ghclass-demo", user = roster$github) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Invited user </span><span style='color: #0000BB;'>'ghclass-anya'</span><span> to org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Invited user </span><span style='color: #0000BB;'>'ghclass-bruno'</span><span> to org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Invited user </span><span style='color: #0000BB;'>'ghclass-celine'</span><span> to org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Invited user </span><span style='color: #0000BB;'>'ghclass-diego'</span><span> to org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #BBBB00;'>ℹ</span><span> User </span><span style='color: #0000BB;'>'ghclass-elijah'</span><span> is already a pending member of org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #BBBB00;'>ℹ</span><span> User </span><span style='color: #0000BB;'>'ghclass-francis'</span><span> is already a pending member of org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. </span></CODE></PRE> -- ```r org_members("ghclass-demo", include_admins = FALSE) ``` ``` ## character(0) ``` ```r org_pending_members("ghclass-demo") ``` ``` ## [1] "ghclass-anya" "ghclass-bruno" "ghclass-elijah" "ghclass-francis" ## [5] "ghclass-celine" ``` --- background-image: url("imgs/02_github_members.png") background-position: center background-size: contain --- background-image: url("imgs/03_github_pending.png") background-position: center background-size: contain --- ## A few days later ... ```r org_members("ghclass-demo", include_admins = FALSE) ``` ``` ## [1] "ghclass-anya" "ghclass-bruno" "ghclass-celine" "ghclass-diego" ``` ```r org_pending_members("ghclass-demo") ``` ``` ## [1] "ghclass-elijah" "ghclass-francis" ``` -- ## several emails and a week later ... ```r org_members("ghclass-demo", include_admins = FALSE) ``` ``` ## [1] "ghclass-anya" "ghclass-bruno" "ghclass-celine" "ghclass-diego" ## [5] "ghclass-elijah" "ghclass-francis" ``` -- ```r org_pending_members("ghclass-demo") ``` ``` ## character(0) ``` --- background-image: url("imgs/04_github_accepted.png") background-position: center background-size: contain --- ## Setup Teams ```r roster ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #949494;'># A tibble: 6 x 5</span><span> ## uid email github hw01 hw02 ## </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> </span><span style='color: #949494;font-style: italic;'><chr></span><span> ## </span><span style='color: #BCBCBC;'>1</span><span> za17 anya@school.edu ghclass-anya hw01-team01 hw02-team01 ## </span><span style='color: #BCBCBC;'>2</span><span> kb34 bruno@school.edu ghclass-bruno hw01-team02 hw02-team02 ## </span><span style='color: #BCBCBC;'>3</span><span> ac13 celine@school.edu ghclass-celine hw01-team03 hw02-team03 ## </span><span style='color: #BCBCBC;'>4</span><span> bd88 diego@school.edu ghclass-diego hw01-team01 hw02-team03 ## </span><span style='color: #BCBCBC;'>5</span><span> se01 elijah@school.edu ghclass-elijah hw01-team02 hw02-team01 ## </span><span style='color: #BCBCBC;'>6</span><span> df00 francis@school.edu ghclass-francis hw01-team03 hw02-team02 </span></CODE></PRE> -- ```r team_create("ghclass-demo", team = roster$hw01) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw01-team01'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw01-team02'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw01-team03'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. </span></CODE></PRE> -- ```r team_invite("ghclass-demo", user = roster$github, team = roster$hw01) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-anya'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-diego'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-bruno'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-elijah'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-celine'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-francis'</span><span> to team </span><span style='color: #0000BB;'>'hw01-team03'</span><span>. </span></CODE></PRE> --- background-image: url("imgs/05_github_org_teams.png") background-position: center background-size: contain --- background-image: url("imgs/06_github_teams.png") background-position: center background-size: contain --- ## Setup Repos ```r roster$hw01 ``` ``` ## [1] "hw01-team01" "hw01-team02" "hw01-team03" "hw01-team01" "hw01-team02" ## [6] "hw01-team03" ``` -- ```r repo_create("ghclass-demo", name = roster$hw01) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. </span></CODE></PRE> -- ```r repo_add_team(repo = org_repos("ghclass-demo", filter = "hw01-"), team = org_teams("ghclass-demo", filter = "hw01-")) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw01-team01'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw01-team02'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw01-team03'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. </span></CODE></PRE> --- background-image: url("imgs/07_github_repos.png") background-position: center background-size: contain --- background-image: url("imgs/08_github_repo_empty.png") background-position: center background-size: contain --- ## Provide Template Code ```r (repos = org_repos("ghclass-demo", filter = "hw01-")) ``` ``` ## [1] "ghclass-demo/hw01-team01" "ghclass-demo/hw01-team02" ## [3] "ghclass-demo/hw01-team03" ``` -- ```r repo_mirror(source_repo = "Sta323-Sp19/hw1", target_repo = repos) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'Sta323-Sp19/hw1'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Removed local copy of </span><span style='color: #0000BB;'>'Sta323-Sp19/hw1'</span><span> </span></CODE></PRE> --- background-image: url("imgs/09_github_mirrored.png") background-position: center background-size: contain --- background-image: url("imgs/10_github_readme1.png") background-position: center background-size: contain --- ## Save some steps ```r org_create_assignment(org = "ghclass-demo", repo = roster$hw02, user = roster$github, team = roster$hw02, source_repo = "Sta323-Sp19/hw2") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw02-team01'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw02-team02'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created team </span><span style='color: #0000BB;'>'hw02-team03'</span><span> in org </span><span style='color: #0000BB;'>'ghclass-demo'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-anya'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-elijah'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-bruno'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-francis'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-celine'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added </span><span style='color: #0000BB;'>'ghclass-diego'</span><span> to team </span><span style='color: #0000BB;'>'hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw02-team01'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw02-team02'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added team </span><span style='color: #0000BB;'>'hw02-team03'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'Sta323-Sp19/hw2'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team03'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'hw2'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw02-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Removed local copy of </span><span style='color: #0000BB;'>'Sta323-Sp19/hw2'</span><span> </span></CODE></PRE> --- ## Individual assignments (e.g. exams) ```r org_create_assignment(org = "ghclass-demo", repo = paste0("exam1-", roster$github), user = roster$github, source_repo = "Sta323-Sp19/midterm1") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-anya'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-bruno'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-celine'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-diego'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-elijah'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-francis'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-anya'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-anya'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-bruno'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-bruno'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-celine'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-celine'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-diego'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-diego'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-elijah'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-elijah'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added user </span><span style='color: #0000BB;'>'ghclass-francis'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-francis'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'Sta323-Sp19/midterm1'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-anya'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-bruno'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-celine'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-diego'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-elijah'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Pushed (mirror) </span><span style='color: #0000BB;'>'midterm1'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/exam1-ghclass-francis'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Removed local copy of </span><span style='color: #0000BB;'>'Sta323-Sp19/midterm1'</span><span> </span></CODE></PRE> --- ## Making Changes ```r repo_add_file(repo = org_repos("ghclass-demo", "hw01-"), file = "files/fizzbuzz.png") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. </span></CODE></PRE> ```r repo_add_file(repo = org_repos("ghclass-demo", "hw01-"), file = "files/fizzbuzz.png", overwrite = TRUE) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Added file </span><span style='color: #0000BB;'>'fizzbuzz.png'</span><span> to repo </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. </span></CODE></PRE> --- ## Modify a file ```r repo_modify_file(repo = org_repos("ghclass-demo", "hw01-"), file = "README.md", pattern = "on Thursday 1/24/2019.", content = "on Wednesday 10/07/2019.") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Modified file </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01/README.md'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Modified file </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02/README.md'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Modified file </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03/README.md'</span><span>. </span></CODE></PRE> --- background-image: url("imgs/10_github_readme1.png") background-position: center background-size: contain --- background-image: url("imgs/11_github_readme2.png") background-position: center background-size: contain --- background-image: url("imgs/12_github_readme3.png") background-position: center background-size: contain --- ## Collect student work ```r local_repo_clone(repo = org_repos("ghclass-demo", "hw01-"), local_path = "hw01") ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team02'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team03'</span><span>. </span></CODE></PRE> -- <img src="imgs/12.5_github_clone.png" width="65%" style="display: block; margin: auto;" /> --- ## Feedback? ```r repo_style("ghclass-demo/hw01-team01", files = "*.Rmd", draft = TRUE) ``` <PRE class="fansi fansi-output"><CODE>## <span style='color: #00BB00;'>✔</span><span> Created branch </span><span style='color: #0000BB;'>'styler'</span><span> from </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Cloned </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01@styler'</span><span>. ## </span><span style='color: #00BB00;'>✔</span><span> Created pull request for </span><span style='color: #0000BB;'>'ghclass-demo/hw01-team01 (master <= styler)'</span><span>. </span></CODE></PRE> --- background-image: url("imgs/13_github_pull_req.png") background-position: center background-size: contain --- background-image: url("imgs/14_github_diff.png") background-position: center background-size: contain --- ## Putting it all together This is an example from my Organization folder for my Statistical Computing course last Spring: ```r library(ghclass) library(dplyr) df = readr::read_csv("hw2_teams.csv") team_create("Sta323-Sp19", team = df$team) team_invite("Sta323-Sp19", df$github, df$team) repo_create("Sta323-Sp19", df$team) repo_add_team(org_repos("Sta323-Sp19","hw2-"), org_teams("Sta323-Sp19","hw2-")) mirror_repo("Sta323-Sp19/hw2", org_repos("Sta323-Sp19","hw2-")) wercker_add(repo = org_repos("Sta323-Sp19","hw2-"), wercker_org = "Sta323-Sp19") branch_create( repo = paste0("Sta323-Sp19/", df$team), cur_branch = "master", new_branch = df$github ) ``` --- ## Future Work * We will be submitting to CRAN in the next month * Active summer project adding functionality for peer review by Mine Cetinkaya-Rundel and Therese Anders * Support for GitHub actions for automated feedback ([rundel/wercker](https://github.com/rundel/wercker) replacement) * Support more workflows, if you GitHub based workflow for teaching that was not reflected here please get in touch. --- # Thank you! <br/> .middle[ .center[ <div style="width: 98%"> <table class="contact" style="text-align: left; font-size: 120%; margin-left:auto; margin-right:auto; width:50%;"> <tbody> <tr> <td style="vertical-align: middle;"> <i class="fas fa-box fa-fw fa-2x"></i> </td> <td> <a href="https://github.com/rundel/ghclass">rundel/ghclass</a> </td> </tr> <tr><td><br/></td></tr> <tr> <td style="vertical-align: middle;"> <i class="far fa-file-powerpoint fa-fw fa-2x"></i> </td> <td> <a href="http://bit.ly/User2019_ghclass">bit.ly/User2019_ghclass</a> </td> </tr> <tr><td><br/></td></tr> <tr> <td style="vertical-align: middle;"> <i class="fab fa-github-square fa-fw fa-2x"></i> </td> <td> <a href="https://github.com/rundel">github.com/rundel</a> </td> </tr> <tr><td><br/></td></tr> <tr> <td style="vertical-align: middle;"> <i class="fas fa-envelope fa-fw fa-2x"></i> </td> <td> <a href="mailto:rundel@gmail.com">rundel@gmail.com</a> </td> </tr> <tr><td><br/></td></tr> <tr> <td style="vertical-align: middle;"> <i class="fab fa-twitter-square fa-fw fa-2x"></i> </td> <td> <a href="https://twitter.com/rundel">@rundel</a> </td> </tr> </tbody> </table> </div> ] ]