Skip to content

Commit 81afeab

Browse files
committed
Baseline lab automation for lab
1 parent 8c201ea commit 81afeab

File tree

7 files changed

+300
-0
lines changed

7 files changed

+300
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
name: Build Lab-Issue Basics template
3+
about: 'This template was created to save typing in the '
4+
title: Investigate Issue Basics
5+
labels: ''
6+
7+
---
8+
9+
# Issue Basics
10+
11+
This task describes the lab steps required to complete the "Issue Basics" tasks. As a template item, this description was filled out for you in advance (to save typing). Generally, you will use templates to get started with a standard format and content but add additional information. In this case, the issue is complete as-is...
12+
13+
To complete this task you will:
14+
- [x] Use an issue template (done)
15+
- [x] Review markdown used to format content in GitHub. You're looking at it now, but if you aren't already familiar with markdown you can refer to [this link](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github). If you've already saved it and want to review the source markdown you can edit the description to see the unformatted text.
16+
- [ ] Apply Labels
17+
- [ ] Apply Milestones
18+
- [ ] Query Issues
19+
- [ ] Verify automation triggered by issues

.github/scripts/issue-seeds.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[
2+
{ "id": 0, "title": "Learning GitHub Issues Batch" },
3+
{ "id": 1, "title": "Exercise Project Fundamentals", "type": "Feature"},
4+
{ "title": "Create a new project", "type": "Task", "parent": 1},
5+
{ "title": "Add all of the remaining issues", "type": "Task", "parent": 1},
6+
{ "id": 2, "title": "Customize Status and Fields", "type": "Feature", "labels": "enhancement" },
7+
{ "title": "Add priority field", "type": "Task", "parent": 2},
8+
{ "title": "Add start and end date fields", "type": "Task", "parent": 2},
9+
{ "title": "Add 'Paused' status", "type": "Task", "parent": 2},
10+
{ "id": 3, "title": "Filter Project Data", "type": "Feature", "labels": "enhancement" },
11+
{ "title": "Rename view 'Feature Planning'", "type": "Task", "parent": 3},
12+
{ "title": "Add Feature/Bug filter", "type": "Task", "parent": 3},
13+
{ "id": 4, "title": "Add 'Release Planning' view", "type": "Feature" },
14+
{ "title": "Populate date fields", "type": "Task", "parent": 4},
15+
{ "title": "Duplicate 'Feature Planning'", "type": "Task", "parent": 4},
16+
{ "title": "Rename to 'Release Roadmap' and set 'Roadmap' view", "type": "Task", "parent": 4},
17+
{ "title": "Scale to quarter and sort by End date", "type": "Task", "parent": 4},
18+
{ "title": "Refine release dates", "type": "Task", "parent": 4},
19+
{ "id": 5, "title": "Add Board view for tasks", "type": "Feature" },
20+
{ "title": "Add a view named 'Task Board' filtered on Tasks and untyped issues", "type": "Task", "parent": 5},
21+
{ "title": "Add a Parent Issue slice, Group by Assignees, and add the Labels field", "type": "Task", "parent": 5},
22+
{ "title": "Fix the typo in the README file", "type": "Bug", "body": "The 'Abstract' header on line 3 is misspelled." }
23+
]

.github/scripts/prepare-lab-env.sh

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#!/bin/bash
2+
# Bash script to set up GitHub lab environment dedicated to Issues and Projects.
3+
4+
# If "--delete" is passed as an argument, delete all issues in the repository
5+
if [[ "$1" == "--delete" || "$1" == "--seed-all" ]]; then
6+
echo "Deleting all issues..."
7+
gh issue list --limit 1000 | awk '{print $1}' | xargs -I {} gh issue delete {} --yes
8+
fi
9+
10+
# If "--seed" is passed as an argument, automatically create issues that are meant to be manually created
11+
if [[ "$1" == "--seed-all" ]]; then
12+
gh issue create \
13+
--title "Investigate Issue Basics" \
14+
--body "
15+
# Issue Basics
16+
17+
This task describes the lab steps required to complete the Issue Basics tasks. As a template item, this description was filled out for you in advance (to save typing). Generally, you will use templates to get started with a standard format and content but add additional information. In this case, the issue is complete as-is...
18+
19+
To complete this task you will:
20+
- [x] Use an issue template (done)
21+
- [x] Review markdown used to format content in GitHub. You're looking at it now, but if you aren't already familiar with markdown you can refer to [this link](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github). If you've already saved it and want to review the source markdown you can edit the description to see the unformatted text.
22+
- [ ] Apply Labels
23+
- [ ] Apply Milestones
24+
- [ ] Query Issues
25+
- [ ] Verify automation triggered by issues" \
26+
--assignee "@me"
27+
fi
28+
29+
# Function to load issue seeds from a JSON file
30+
load_issue_seeds() {
31+
# Check if jq is installed
32+
if ! command -v jq &> /dev/null; then
33+
echo "Error: jq is not installed. Please install it with: sudo apt-get install jq" >&2
34+
return 1
35+
fi
36+
37+
# Check if file exists
38+
local file_path="issue-seeds.json"
39+
if [[ ! -f "$file_path" ]]; then
40+
echo "Error: $file_path not found in current directory." >&2
41+
return 1
42+
fi
43+
44+
# Read the JSON file and return the content
45+
local json_content
46+
json_content=$(jq '.' "$file_path")
47+
48+
# Check if the JSON is valid
49+
if [[ $? -ne 0 ]]; then
50+
echo "Error: Failed to parse JSON file." >&2
51+
return 1
52+
fi
53+
54+
# Echo the JSON content
55+
echo "$json_content"
56+
57+
}
58+
59+
# Function to create a GitHub issue from a JSON issue object
60+
create_issue_from_json() {
61+
local issue_json="$1"
62+
63+
# Extract issue properties with proper error handling
64+
local id=$(echo "$issue_json" | jq -r '.id // empty')
65+
local title=$(echo "$issue_json" | jq -r '.title // empty')
66+
local body=$(echo "$issue_json" | jq -r '.body // empty')
67+
# local labels=$(echo "$issue_json" | jq -r '.labels // [] | join(",")')
68+
local labels=$(echo "$issue_json" | jq -r '.labels // empty')
69+
local milestone=$(echo "$issue_json" | jq -r '.milestone // empty')
70+
local parent=$(echo "$issue_json" | jq -r '.parent // empty')
71+
72+
# Validate required fields
73+
if [[ -z "$title" ]]; then
74+
echo "Error: Issue title is required." >&2
75+
return 1
76+
fi
77+
78+
echo "Creating issue: $title"
79+
80+
# Build the gh issue create command
81+
local cmd="gh issue create --title \"$title\" --body \"$body\""
82+
83+
# Add labels if provided
84+
if [[ -n "$labels" && "$labels" != "" ]]; then
85+
cmd="$cmd --label \"$labels\""
86+
fi
87+
88+
# Add milestone if provided
89+
if [[ -n "$milestone" && "$milestone" != "null" ]]; then
90+
cmd="$cmd --milestone \"$milestone\""
91+
fi
92+
93+
# Execute the command to create the issue
94+
issue_url=$(eval "$cmd")
95+
96+
# Check if issue was created successfully
97+
if [[ $? -eq 0 ]]; then
98+
echo "Successfully created issue: $issue_url"
99+
100+
# Parse the issue number from the URL
101+
issue_number=$(echo "$issue_url" | grep -oE '[0-9]+$')
102+
103+
# Modify the URL to create the related API URL
104+
api_url=$(echo "/repos/$issue_url" | sed 's/https:\/\/github.com\///')
105+
106+
# Set the issue Type based on the JSON "type" field
107+
issue_type=$(echo "$issue_json" | jq -r '.type // empty')
108+
109+
# Use the GitHub CLI to call the api_url and apply the issue_type
110+
echo "Setting issue type to: $issue_type"
111+
gh api -X PATCH "$api_url" -f type="$issue_type"
112+
113+
# Capture the parent issue number if provided
114+
if [[ -n "$id" && "$id" != "null" ]]; then
115+
echo "Capturing issue ID[$id] = $issue_number"
116+
parent_issue_numbers[$id]=$issue_number
117+
fi
118+
119+
# If a parent issue is specified, create the relationship
120+
if [[ -n "$parent" && "$parent" != "null" ]]; then
121+
echo "Attempting to add relationship with parent issue: $parent"
122+
123+
# Look up this issue's node_id
124+
child_id=$(gh api -X GET "$api_url" | jq -r '.id // empty')
125+
126+
# Check the parent issue number array
127+
if [[ "${parent_issue_numbers[$parent]}" ]]; then
128+
129+
# create a version of the API URL for the parent issue
130+
parent_id=${parent_issue_numbers[$parent]}
131+
parent_api_url=$(echo "$api_url" | sed -E "s|/([0-9]+)$|/$parent_id/sub_issues|")
132+
133+
# Add the sub-issue relationship via the GitHub API
134+
echo "Adding sub-issue relationship from $parent_id to $issue_number"
135+
gh api $parent_api_url -X POST -F sub_issue_id=$child_id
136+
fi
137+
fi
138+
139+
return 0
140+
else
141+
echo "Failed to create issue: $title" >&2
142+
return 1
143+
fi
144+
}
145+
146+
# ------------------------------------------------------------
147+
# Seed automation issues required for the lab
148+
# ------------------------------------------------------------
149+
if [[ "$1" == "" || "$1" == "--seed-all" ]]; then
150+
151+
# Call the function and store the result in a variable
152+
echo "Reading seed issues for the lab..."
153+
issue_seeds_json=$(load_issue_seeds)
154+
155+
if [[ $? -eq 0 ]]; then
156+
echo "Successfully loaded $(echo "$issue_seeds_json" | jq 'length') issue seeds."
157+
158+
# Initialize an array for parent issue numbers
159+
declare -a parent_issue_numbers=()
160+
161+
# Loop through each issue in the JSON array
162+
for i in $(seq 0 $(( $(echo "$issue_seeds_json" | jq 'length') - 1 ))); do
163+
# Extract the issue object
164+
issue=$(echo "$issue_seeds_json" | jq ".[$i]")
165+
166+
# Create issue from the JSON object
167+
create_issue_from_json "$issue"
168+
169+
# Optional: Add a small delay between issue creation to avoid rate limits
170+
# sleep 1
171+
done
172+
else
173+
echo "Failed to load issue seeds JSON"
174+
exit 1
175+
fi
176+
fi
177+

.github/workflows/.run-once

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The purpose of this file is to cause a trigger of a workflow when this repo is first created from a template. If you modify this file later and commit the code, it will re-run that workflow, which may have unintended consequences.

.github/workflows/issue-ping.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Issue automation lab sample
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
7+
permissions:
8+
issues: write
9+
contents: read
10+
11+
jobs:
12+
respond_to_ping:
13+
runs-on: ubuntu-latest
14+
if: contains(github.event.comment.body, 'ping')
15+
16+
steps:
17+
- name: Respond with pong
18+
uses: actions/github-script@v6
19+
with:
20+
github-token: ${{ secrets.GITHUB_TOKEN }}
21+
script: |
22+
github.rest.issues.createComment({
23+
issue_number: context.issue.number,
24+
owner: context.repo.owner,
25+
repo: context.repo.repo,
26+
body: 'pong'
27+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
on:
2+
# Manual run with parameter for what to do
3+
workflow_dispatch:
4+
inputs:
5+
command:
6+
required: false
7+
type: choice
8+
options:
9+
- --delete
10+
- --seed-all
11+
# Automatic run when this is first created from a template
12+
push:
13+
branches:
14+
- main
15+
paths:
16+
- .github/workflows/.run-once
17+
18+
permissions:
19+
issues: write
20+
contents: read
21+
22+
jobs:
23+
seed_issues:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/[email protected]
27+
- run: ./prepare-lab-env.sh $OPTION
28+
shell: bash
29+
working-directory: .github/scripts
30+
env:
31+
OPTION: ${{ inputs.command }}
32+
GH_TOKEN: ${{ github.token }}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Dave McKinstry
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)