Skip to content

Commit 0a8de68

Browse files
committed
Enhance README and script to support field configuration for output customization
1 parent b8a6534 commit 0a8de68

2 files changed

Lines changed: 253 additions & 6 deletions

File tree

README.md

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ $ gh repo-stats --help
2020
Usage: gh repo-stats [options]
2121

2222
Options:
23+
-b, --batch : Number of repositories to process in parallel
24+
Default: 1 (sequential processing)
25+
-c, --config : Path to field configuration CSV file (Field_Name,Should_Fetch format)
26+
If not provided, all fields are fetched
2327
-d, --debug : Enable Debug logging
2428
-e, --extra-page-size : Set the pagination size for subsequent, paginated GraphQL queries; reduce if timeout occurs
2529
Default: 50
@@ -49,6 +53,7 @@ Description:
4953
Example:
5054
gh repo-stats -o my-org-name
5155
gh repo-stats -o my-org-name -H github.example.com
56+
gh repo-stats -o my-org-name -c fields-config.csv
5257
```
5358
5459
## Permissions
@@ -72,7 +77,7 @@ The permissions needed by `gh repo-stats` depends based on `-y, --token-type`:
7277
`gh repo-stats` produces either a visual table or `*.csv` file containing detailed information about various records within repositories.
7378
7479
```csv
75-
Org_Name,Repo_Name,Is_Empty,Last_Push,Last_Update,Latest_Commit_SHA,Latest_Committed_At,Latest_Commit_Branch,Default_Branch,isFork,isArchive,Repo_Size(mb),Record_Count,Collaborator_Count,Protected_Branch_Count,PR_Review_Count,Milestone_Count,Issue_Count,PR_Count,PR_Review_Comment_Count,Commit_Comment_Count,Issue_Comment_Count,Issue_Event_Count,Release_Count,Project_Count,Branch_Count,Tag_Count,Discussion_Count,Has_Wiki,Full_URL,Migration_Issue,Created
80+
Org_Name,Repo_Name,Is_Empty,Last_Push,Last_Update,Latest_Commit_SHA,Latest_Committed_At,Latest_Commit_Branch,Default_Branch,isFork,isArchive,Repo_Size_mb,Record_Count,Collaborator_Count,Protected_Branch_Count,PR_Review_Count,Milestone_Count,Issue_Count,PR_Count,PR_Review_Comment_Count,Commit_Comment_Count,Issue_Comment_Count,Issue_Event_Count,Release_Count,Project_Count,Branch_Count,Tag_Count,Discussion_Count,Has_Wiki,Full_URL,Migration_Issue,Created
7681
tinyfists,actions-experiments,false,2023-03-10T16:15:27Z,2022-10-28T19:38:34Z,abc123def456,2023-03-10T16:15:27Z,feature-branch,main,false,false,0,19,18,0,0,0,0,1,0,0,0,0,0,0,2,0,0,true,https://github.com/tinyfists/actions-experiments,FALSE,2020-01-01T13:37:00Z
7782
```
7883
@@ -89,7 +94,7 @@ tinyfists,actions-experiments,false,2023-03-10T16:15:27Z,2022-10-28T19:38:34Z,ab
8994
- `Default_Branch`: Default branch of the repository (e.g., main, master), or "No default branch" if none exists
9095
- `isFork`: Whether the repository is a fork
9196
- `isArchive`: Whether the repository is archived
92-
- `Repo_Size(mb)`: Size of the repository in megabytes
97+
- `Repo_Size_mb`: Size of the repository in megabytes
9398
- `Record_Count`: Number of database records this repository represents
9499
- `Collaborator_Count`: Number of users who have contributed to this repository
95100
- `Protected_Branch_Count`: Number of branch protection rules on this repository
@@ -112,3 +117,71 @@ tinyfists,actions-experiments,false,2023-03-10T16:15:27Z,2022-10-28T19:38:34Z,ab
112117
- 60,000 or more number of objects being imported
113118
- 1.5 GB or larger size on disk
114119
- `Created`: Date/time when the repository was created
120+
121+
## Field Configuration
122+
123+
You can customize which fields are included in the output by using a field configuration CSV file with the `-c` or `--config` option. This is useful when you only need specific fields and want to reduce the output size.
124+
125+
### Configuration File Format
126+
127+
Create a CSV file with the following format:
128+
129+
```csv
130+
Field_Name,Should_Fetch
131+
Org_Name,true
132+
Repo_Name,true
133+
Is_Empty,false
134+
Last_Push,true
135+
...
136+
```
137+
138+
- `Field_Name`: The name of the field (must match exactly)
139+
- `Should_Fetch`: `true` to include the field, `false` to exclude it
140+
141+
### Example Configuration File
142+
143+
A sample configuration file `fields-config.csv` is provided in the repository with all fields enabled. You can copy and modify it to suit your needs:
144+
145+
```shell
146+
# Use custom field configuration
147+
gh repo-stats -o my-org-name -c fields-config.csv
148+
```
149+
150+
### Available Fields
151+
152+
| Field Name | Description |
153+
|------------|-------------|
154+
| `Org_Name` | Organization login |
155+
| `Repo_Name` | Repository name |
156+
| `Is_Empty` | Whether the repository is empty |
157+
| `Last_Push` | Date/time when a push was last made |
158+
| `Last_Update` | Date/time when an update was last made |
159+
| `Latest_Commit_SHA` | SHA of the most recent commit |
160+
| `Latest_Committed_At` | Date/time of the most recent commit |
161+
| `Latest_Commit_Branch` | Branch of the most recent commit |
162+
| `Default_Branch` | Default branch of the repository |
163+
| `isFork` | Whether the repository is a fork |
164+
| `isArchived` | Whether the repository is archived |
165+
| `Repo_Size_mb` | Size of the repository in MB |
166+
| `Record_Count` | Number of database records |
167+
| `Collaborator_Count` | Number of collaborators |
168+
| `Protected_Branch_Count` | Number of branch protection rules |
169+
| `PR_Review_Count` | Number of pull request reviews |
170+
| `Milestone_Count` | Number of milestones |
171+
| `Issue_Count` | Number of issues |
172+
| `PR_Count` | Number of pull requests |
173+
| `PR_Review_Comment_Count` | Number of PR review comments |
174+
| `Commit_Comment_Count` | Number of commit comments |
175+
| `Issue_Comment_Count` | Number of issue comments |
176+
| `Issue_Event_Count` | Number of issue events |
177+
| `Release_Count` | Number of releases |
178+
| `Project_Count` | Number of projects |
179+
| `Branch_Count` | Number of branches |
180+
| `Tag_Count` | Number of tags |
181+
| `Discussion_Count` | Number of discussions |
182+
| `Has_Wiki` | Whether wiki is enabled |
183+
| `Full_URL` | Repository URL |
184+
| `Migration_Issue` | Migration issue indicator |
185+
| `Created` | Repository creation date |
186+
187+
**Note**: If no configuration file is specified or the file doesn't exist, all fields will be fetched by default.

gh-repo-stats

Lines changed: 178 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# Default Branch (default branch of the repo, or "No default branch")
2323
# isFork
2424
# isArchived
25-
# Size(mb)
25+
# Size_mb
2626
# Total record count
2727
# Collaborator count
2828
# Protected branches
@@ -73,6 +73,8 @@ REPO_PAGE_SIZE=10
7373
EXTRA_PAGE_SIZE=50
7474
BATCH_SIZE=1 # Number of repos to process in parallel (1 = sequential)
7575
REPOS_TO_PROCESS=() # Global array to accumulate repos for batch processing
76+
FIELD_CONFIG_FILE="" # Path to field configuration CSV file
77+
DISABLED_FIELDS="" # Comma-separated list of disabled fields
7678

7779
################################################################################
7880
#### Function PrintUsage #######################################################
@@ -84,6 +86,8 @@ Usage: gh repo-stats [options]
8486
Options:
8587
-b, --batch : Number of repositories to process in parallel
8688
Default: $BATCH_SIZE (sequential processing)
89+
-c, --config : Path to field configuration CSV file (Field_Name,Should_Fetch format)
90+
If not provided, all fields are fetched
8791
-d, --debug : Enable Debug logging
8892
-e, --extra-page-size : Set the pagination size for subsequent, paginated GraphQL queries; reduce if timeout occurs
8993
Default: $EXTRA_PAGE_SIZE
@@ -135,6 +139,10 @@ while (( "$#" )); do
135139
BATCH_SIZE=$2
136140
shift 2
137141
;;
142+
-c|--config)
143+
FIELD_CONFIG_FILE=$2
144+
shift 2
145+
;;
138146
-d|--debug)
139147
DEBUG=true
140148
export GH_DEBUG=api
@@ -221,6 +229,120 @@ Debug() {
221229
fi
222230
}
223231
################################################################################
232+
#### Function LoadFieldConfig ##################################################
233+
LoadFieldConfig() {
234+
# Initialize - by default all fields are enabled (DISABLED_FIELDS is empty)
235+
DISABLED_FIELDS=""
236+
237+
# If no config file specified, all fields remain enabled
238+
if [[ -z "${FIELD_CONFIG_FILE}" ]]; then
239+
Debug "No field config file specified, all fields enabled"
240+
return 0
241+
fi
242+
243+
# Check if config file exists
244+
if [[ ! -f "${FIELD_CONFIG_FILE}" ]]; then
245+
echo "WARN: Field config file not found: ${FIELD_CONFIG_FILE}"
246+
echo "Proceeding with all fields enabled"
247+
return 0
248+
fi
249+
250+
echo "Loading field configuration from: ${FIELD_CONFIG_FILE}"
251+
252+
# Read the config file and build DISABLED_FIELDS list
253+
local line_num=0
254+
local enabled_count=0
255+
local disabled_count=0
256+
while IFS=',' read -r field_name should_fetch || [[ -n "$field_name" ]]; do
257+
((line_num++))
258+
# Skip header line
259+
if [[ ${line_num} -eq 1 ]]; then
260+
continue
261+
fi
262+
263+
# Trim whitespace
264+
field_name=$(echo "${field_name}" | tr -d '[:space:]')
265+
should_fetch=$(echo "${should_fetch}" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')
266+
267+
# Skip empty lines
268+
if [[ -z "${field_name}" ]]; then
269+
continue
270+
fi
271+
272+
# Track disabled fields
273+
if [[ "${should_fetch}" == "true" ]]; then
274+
((enabled_count++))
275+
Debug "Field enabled: ${field_name}"
276+
elif [[ "${should_fetch}" == "false" ]]; then
277+
DISABLED_FIELDS="${DISABLED_FIELDS},${field_name},"
278+
((disabled_count++))
279+
Debug "Field disabled: ${field_name}"
280+
else
281+
echo "WARN: Invalid value for field ${field_name}: ${should_fetch} (expected true/false)"
282+
fi
283+
done < "${FIELD_CONFIG_FILE}"
284+
285+
echo "Field configuration loaded: ${enabled_count} fields enabled, ${disabled_count} fields disabled"
286+
}
287+
################################################################################
288+
#### Function IsFieldEnabled ###################################################
289+
IsFieldEnabled() {
290+
local field_name="$1"
291+
# Check if field is in the disabled list
292+
if [[ "${DISABLED_FIELDS}" == *",${field_name},"* ]]; then
293+
return 1 # false - field is disabled
294+
else
295+
return 0 # true - field is enabled
296+
fi
297+
}
298+
################################################################################
299+
#### Function BuildOutputRow ###################################################
300+
BuildOutputRow() {
301+
# Build output row based on enabled fields
302+
# Uses global variables for field values
303+
local OUTPUT_ROW=""
304+
305+
IsFieldEnabled "Org_Name" && OUTPUT_ROW="${OUTPUT_ROW}${ORG_NAME},"
306+
IsFieldEnabled "Repo_Name" && OUTPUT_ROW="${OUTPUT_ROW}${REPO_NAME},"
307+
if [[ "$(isCompatibleGHESVersion)" -eq "1" ]]; then
308+
IsFieldEnabled "Is_Empty" && OUTPUT_ROW="${OUTPUT_ROW}${IS_EMPTY},"
309+
fi
310+
IsFieldEnabled "Last_Push" && OUTPUT_ROW="${OUTPUT_ROW}${PUSHED_AT},"
311+
IsFieldEnabled "Last_Update" && OUTPUT_ROW="${OUTPUT_ROW}${UPDATED_AT},"
312+
IsFieldEnabled "Latest_Commit_SHA" && OUTPUT_ROW="${OUTPUT_ROW}${LATEST_COMMIT_SHA},"
313+
IsFieldEnabled "Latest_Committed_At" && OUTPUT_ROW="${OUTPUT_ROW}${LATEST_COMMITTED_AT},"
314+
IsFieldEnabled "Latest_Commit_Branch" && OUTPUT_ROW="${OUTPUT_ROW}${LATEST_COMMIT_BRANCH},"
315+
IsFieldEnabled "Default_Branch" && OUTPUT_ROW="${OUTPUT_ROW}${DEFAULT_BRANCH},"
316+
IsFieldEnabled "isFork" && OUTPUT_ROW="${OUTPUT_ROW}${IS_FORK},"
317+
IsFieldEnabled "isArchived" && OUTPUT_ROW="${OUTPUT_ROW}${IS_ARCHIVED},"
318+
IsFieldEnabled "Repo_Size_mb" && OUTPUT_ROW="${OUTPUT_ROW}${REPO_SIZE},"
319+
IsFieldEnabled "Record_Count" && OUTPUT_ROW="${OUTPUT_ROW}${RECORD_CT},"
320+
IsFieldEnabled "Collaborator_Count" && OUTPUT_ROW="${OUTPUT_ROW}${COLLABORATOR_CT},"
321+
IsFieldEnabled "Protected_Branch_Count" && OUTPUT_ROW="${OUTPUT_ROW}${PROTECTED_BRANCH_CT},"
322+
IsFieldEnabled "PR_Review_Count" && OUTPUT_ROW="${OUTPUT_ROW}${PR_REVIEW_CT},"
323+
IsFieldEnabled "Milestone_Count" && OUTPUT_ROW="${OUTPUT_ROW}${MILESTONE_CT},"
324+
IsFieldEnabled "Issue_Count" && OUTPUT_ROW="${OUTPUT_ROW}${ISSUE_CT},"
325+
IsFieldEnabled "PR_Count" && OUTPUT_ROW="${OUTPUT_ROW}${PR_CT},"
326+
IsFieldEnabled "PR_Review_Comment_Count" && OUTPUT_ROW="${OUTPUT_ROW}${PR_REVIEW_COMMENT_CT},"
327+
IsFieldEnabled "Commit_Comment_Count" && OUTPUT_ROW="${OUTPUT_ROW}${COMMIT_COMMENT_CT},"
328+
IsFieldEnabled "Issue_Comment_Count" && OUTPUT_ROW="${OUTPUT_ROW}${ISSUE_COMMENT_CT},"
329+
IsFieldEnabled "Issue_Event_Count" && OUTPUT_ROW="${OUTPUT_ROW}${ISSUE_EVENT_CT},"
330+
IsFieldEnabled "Release_Count" && OUTPUT_ROW="${OUTPUT_ROW}${RELEASE_CT},"
331+
IsFieldEnabled "Project_Count" && OUTPUT_ROW="${OUTPUT_ROW}${PROJECT_CT},"
332+
IsFieldEnabled "Branch_Count" && OUTPUT_ROW="${OUTPUT_ROW}${BRANCH_CT},"
333+
IsFieldEnabled "Tag_Count" && OUTPUT_ROW="${OUTPUT_ROW}${TAG_CT},"
334+
IsFieldEnabled "Discussion_Count" && OUTPUT_ROW="${OUTPUT_ROW}${DISCUSSION_CT},"
335+
IsFieldEnabled "Has_Wiki" && OUTPUT_ROW="${OUTPUT_ROW}${HAS_WIKI},"
336+
IsFieldEnabled "Full_URL" && OUTPUT_ROW="${OUTPUT_ROW}${URL},"
337+
IsFieldEnabled "Migration_Issue" && OUTPUT_ROW="${OUTPUT_ROW}${MIGRATION_ISSUE},"
338+
IsFieldEnabled "Created" && OUTPUT_ROW="${OUTPUT_ROW}${CREATED_AT},"
339+
340+
# Remove trailing comma
341+
OUTPUT_ROW="${OUTPUT_ROW%,}"
342+
343+
echo "${OUTPUT_ROW}"
344+
}
345+
################################################################################
224346
#### Function Header ###########################################################
225347
Header() {
226348
echo ""
@@ -450,7 +572,48 @@ GenerateFiles() {
450572
IS_EMPTY_HEADER="";
451573
fi
452574

453-
echo "Org_Name,Repo_Name,${IS_EMPTY_HEADER}Last_Push,Last_Update,Latest_Commit_SHA,Latest_Committed_At,Latest_Commit_Branch,Default_Branch,isFork,isArchived,Repo_Size(mb),Record_Count,Collaborator_Count,Protected_Branch_Count,PR_Review_Count,Milestone_Count,Issue_Count,PR_Count,PR_Review_Comment_Count,Commit_Comment_Count,Issue_Comment_Count,Issue_Event_Count,Release_Count,Project_Count,Branch_Count,Tag_Count,Discussion_Count,Has_Wiki,Full_URL,Migration_Issue,Created" >>"${OUTPUT_FILE_NAME}" 2>&1
575+
# Build dynamic header based on enabled fields
576+
HEADER=""
577+
578+
IsFieldEnabled "Org_Name" && HEADER="${HEADER}Org_Name,"
579+
IsFieldEnabled "Repo_Name" && HEADER="${HEADER}Repo_Name,"
580+
if [[ "$(isCompatibleGHESVersion)" -eq "1" ]]; then
581+
IsFieldEnabled "Is_Empty" && HEADER="${HEADER}Is_Empty,"
582+
fi
583+
IsFieldEnabled "Last_Push" && HEADER="${HEADER}Last_Push,"
584+
IsFieldEnabled "Last_Update" && HEADER="${HEADER}Last_Update,"
585+
IsFieldEnabled "Latest_Commit_SHA" && HEADER="${HEADER}Latest_Commit_SHA,"
586+
IsFieldEnabled "Latest_Committed_At" && HEADER="${HEADER}Latest_Committed_At,"
587+
IsFieldEnabled "Latest_Commit_Branch" && HEADER="${HEADER}Latest_Commit_Branch,"
588+
IsFieldEnabled "Default_Branch" && HEADER="${HEADER}Default_Branch,"
589+
IsFieldEnabled "isFork" && HEADER="${HEADER}isFork,"
590+
IsFieldEnabled "isArchived" && HEADER="${HEADER}isArchived,"
591+
IsFieldEnabled "Repo_Size_mb" && HEADER="${HEADER}Repo_Size_mb,"
592+
IsFieldEnabled "Record_Count" && HEADER="${HEADER}Record_Count,"
593+
IsFieldEnabled "Collaborator_Count" && HEADER="${HEADER}Collaborator_Count,"
594+
IsFieldEnabled "Protected_Branch_Count" && HEADER="${HEADER}Protected_Branch_Count,"
595+
IsFieldEnabled "PR_Review_Count" && HEADER="${HEADER}PR_Review_Count,"
596+
IsFieldEnabled "Milestone_Count" && HEADER="${HEADER}Milestone_Count,"
597+
IsFieldEnabled "Issue_Count" && HEADER="${HEADER}Issue_Count,"
598+
IsFieldEnabled "PR_Count" && HEADER="${HEADER}PR_Count,"
599+
IsFieldEnabled "PR_Review_Comment_Count" && HEADER="${HEADER}PR_Review_Comment_Count,"
600+
IsFieldEnabled "Commit_Comment_Count" && HEADER="${HEADER}Commit_Comment_Count,"
601+
IsFieldEnabled "Issue_Comment_Count" && HEADER="${HEADER}Issue_Comment_Count,"
602+
IsFieldEnabled "Issue_Event_Count" && HEADER="${HEADER}Issue_Event_Count,"
603+
IsFieldEnabled "Release_Count" && HEADER="${HEADER}Release_Count,"
604+
IsFieldEnabled "Project_Count" && HEADER="${HEADER}Project_Count,"
605+
IsFieldEnabled "Branch_Count" && HEADER="${HEADER}Branch_Count,"
606+
IsFieldEnabled "Tag_Count" && HEADER="${HEADER}Tag_Count,"
607+
IsFieldEnabled "Discussion_Count" && HEADER="${HEADER}Discussion_Count,"
608+
IsFieldEnabled "Has_Wiki" && HEADER="${HEADER}Has_Wiki,"
609+
IsFieldEnabled "Full_URL" && HEADER="${HEADER}Full_URL,"
610+
IsFieldEnabled "Migration_Issue" && HEADER="${HEADER}Migration_Issue,"
611+
IsFieldEnabled "Created" && HEADER="${HEADER}Created,"
612+
613+
# Remove trailing comma
614+
HEADER="${HEADER%,}"
615+
616+
echo "${HEADER}" >>"${OUTPUT_FILE_NAME}" 2>&1
454617

455618
#######################
456619
# Load the error code #
@@ -1092,7 +1255,10 @@ ParseRepoDataBatch() {
10921255
########################
10931256
# Write to temp file #
10941257
########################
1095-
echo "${ORG_NAME},${REPO_NAME},${IS_EMPTY}${PUSHED_AT},${UPDATED_AT},${LATEST_COMMIT_SHA},${LATEST_COMMITTED_AT},${LATEST_COMMIT_BRANCH},${DEFAULT_BRANCH},${IS_FORK},${IS_ARCHIVED},${REPO_SIZE},${RECORD_CT},${COLLABORATOR_CT},${PROTECTED_BRANCH_CT},${PR_REVIEW_CT},${MILESTONE_CT},${ISSUE_CT},${PR_CT},${PR_REVIEW_COMMENT_CT},${COMMIT_COMMENT_CT},${ISSUE_COMMENT_CT},${ISSUE_EVENT_CT},${RELEASE_CT},${PROJECT_CT},${BRANCH_CT},${TAG_CT},${DISCUSSION_CT},${HAS_WIKI},${URL},${MIGRATION_ISSUE},${CREATED_AT}" > "${TEMP_OUTPUT_FILE}"
1258+
# Remove trailing comma from IS_EMPTY if present (it's handled by BuildOutputRow)
1259+
IS_EMPTY="${IS_EMPTY%,}"
1260+
OUTPUT_DATA=$(BuildOutputRow)
1261+
echo "${OUTPUT_DATA}" > "${TEMP_OUTPUT_FILE}"
10961262

10971263
echo "Completed analysis for Repo: ${REPO_NAME}"
10981264
}
@@ -1201,7 +1367,10 @@ ParseRepoData() {
12011367
########################
12021368
# Write it to the file #
12031369
########################
1204-
echo "${ORG_NAME},${REPO_NAME},${IS_EMPTY}${PUSHED_AT},${UPDATED_AT},${LATEST_COMMIT_SHA},${LATEST_COMMITTED_AT},${LATEST_COMMIT_BRANCH},${DEFAULT_BRANCH},${IS_FORK},${IS_ARCHIVED},${REPO_SIZE},${RECORD_CT},${COLLABORATOR_CT},${PROTECTED_BRANCH_CT},${PR_REVIEW_CT},${MILESTONE_CT},${ISSUE_CT},${PR_CT},${PR_REVIEW_COMMENT_CT},${COMMIT_COMMENT_CT},${ISSUE_COMMENT_CT},${ISSUE_EVENT_CT},${RELEASE_CT},${PROJECT_CT},${BRANCH_CT},${TAG_CT},${DISCUSSION_CT},${HAS_WIKI},${URL},${MIGRATION_ISSUE},${CREATED_AT}" >>"${OUTPUT_FILE_NAME}"
1370+
# Remove trailing comma from IS_EMPTY if present (it's handled by BuildOutputRow)
1371+
IS_EMPTY="${IS_EMPTY%,}"
1372+
OUTPUT_DATA=$(BuildOutputRow)
1373+
echo "${OUTPUT_DATA}" >>"${OUTPUT_FILE_NAME}"
12051374

12061375
#######################
12071376
# Load the error code #
@@ -1869,6 +2038,11 @@ ValidateInput() {
18692038
##########
18702039
Header
18712040

2041+
###########################
2042+
# Load Field Config #
2043+
###########################
2044+
LoadFieldConfig
2045+
18722046
#########################
18732047
# Validate JQ installed #
18742048
#########################

0 commit comments

Comments
 (0)