Skip to content

Commit dfc1398

Browse files
committed
labeler improvements
Signed-off-by: Jeffrey Sica <me@jeefy.dev>
1 parent 290b615 commit dfc1398

File tree

5 files changed

+140
-25
lines changed

5 files changed

+140
-25
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: "Labeler Action"
2+
description: "A reusable action to label issues and PRs using a Docker container."
3+
4+
inputs:
5+
owner:
6+
description: "The repository owner."
7+
required: true
8+
repo:
9+
description: "The repository name."
10+
required: true
11+
issue_number:
12+
description: "The issue or PR number."
13+
required: true
14+
comment_body:
15+
description: "The body of the comment triggering the action."
16+
required: true
17+
18+
runs:
19+
using: "docker"
20+
image: "ghcr.io/cncf/automation-labeler:main"
21+
args:
22+
- "${{ inputs.owner }}"
23+
- "${{ inputs.repo }}"
24+
- "${{ inputs.issue_number }}"
25+
- "${{ inputs.comment_body }}"

.github/workflows/labeler-build.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Auto Label Issues and PRs
2+
3+
on:
4+
push:
5+
branches:
6+
- "*"
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout code
13+
uses: actions/checkout@v4
14+
15+
- name: Build and push Docker image
16+
uses: docker/build-push-action@v4
17+
with:
18+
context: ./utilities/labeler
19+
file: ./utilities/labeler/Dockerfile
20+
push: true
21+
tags: cncf/automation-labeler:${{ github.ref_name }}

.github/workflows/labeler.yml

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,10 @@ jobs:
88
label:
99
runs-on: ubuntu-latest
1010
steps:
11-
- name: Checkout code
12-
uses: actions/checkout@v4
13-
14-
- name: Set up Go
15-
uses: actions/setup-go@v5
11+
- name: Run labeler action
12+
uses: ./github/actions/labeler-action
1613
with:
17-
go-version: '1.22'
18-
19-
- name: Build labeler
20-
run: |
21-
cd utilities/labeler
22-
go build -o labeler
23-
24-
- name: Run labeler on comment
25-
env:
26-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27-
run: |
28-
cd utilities/labeler
29-
# Extract command and args from comment body
30-
COMMENT_BODY="${{ github.event.comment.body }}"
31-
OWNER="${{ github.repository_owner }}"
32-
REPO="${{ github.event.repository.name }}"
33-
NUMBER="${{ github.event.issue.number }}"
34-
# Always run the labeler; all logic is handled in Go
35-
./labeler "$OWNER" "$REPO" "$NUMBER" "$COMMENT_BODY"
14+
owner: ${{ github.repository_owner }}
15+
repo: ${{ github.event.repository.name }}
16+
issue_number: ${{ github.event.issue.number }}
17+
comment_body: ${{ github.event.comment.body }}

utilities/labeler/Dockerfile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Use the official Golang image as a base image
2+
FROM golang:1.24.5 AS builder
3+
4+
# Set the working directory
5+
WORKDIR /app
6+
7+
# Copy go.mod and go.sum files
8+
COPY go.mod go.sum ./
9+
10+
# Download dependencies
11+
RUN go mod download
12+
13+
# Copy the rest of the application code
14+
COPY . .
15+
16+
# Build the Go binary
17+
RUN go build -o labeler main.go
18+
19+
# Use a minimal base image for the final container
20+
FROM scratch
21+
22+
# Set the working directory
23+
WORKDIR /app
24+
25+
# Copy the binary from the builder stage
26+
COPY --from=builder /app/labeler /app/labeler
27+
28+
# Set the entrypoint
29+
ENTRYPOINT ["/app/labeler"]

utilities/labeler/main.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,67 @@ func indexOf(s, substr string) int {
152152
return strings.Index(s, substr)
153153
}
154154

155+
func ensureLabelExists(ctx context.Context, client *github.Client, owner, repo, labelName, color, description string) {
156+
// Fetch existing labels
157+
existingLabels, _, err := client.Issues.ListLabels(ctx, owner, repo, nil)
158+
if err != nil {
159+
log.Fatalf("failed to fetch labels: %v", err)
160+
}
161+
162+
// Check if the label already exists
163+
for _, lbl := range existingLabels {
164+
if lbl.GetName() == labelName {
165+
// Update label if color or description differs
166+
if lbl.GetColor() != color || lbl.GetDescription() != description {
167+
_, _, err := client.Issues.EditLabel(ctx, owner, repo, labelName, &github.Label{
168+
Name: &labelName,
169+
Color: &color,
170+
Description: &description,
171+
})
172+
if err != nil {
173+
log.Printf("failed to update label %s: %v", labelName, err)
174+
}
175+
}
176+
return
177+
}
178+
}
179+
180+
// Create the label if it doesn't exist
181+
_, _, err = client.Issues.CreateLabel(ctx, owner, repo, &github.Label{
182+
Name: &labelName,
183+
Color: &color,
184+
Description: &description,
185+
})
186+
if err != nil {
187+
log.Printf("failed to create label %s: %v", labelName, err)
188+
}
189+
}
190+
155191
func applyLabel(ctx context.Context, client *github.Client, owner, repo string, issueNum int, label string) {
156192
fmt.Printf("Applying label: %s\n", label)
157-
_, _, err := client.Issues.AddLabelsToIssue(ctx, owner, repo, issueNum, []string{label})
193+
194+
// Fetch existing labels
195+
existingLabels, _, err := client.Issues.ListLabels(ctx, owner, repo, nil)
196+
if err != nil {
197+
log.Printf("failed to fetch labels: %v", err)
198+
return
199+
}
200+
201+
// Check if the label exists
202+
labelExists := false
203+
for _, lbl := range existingLabels {
204+
if lbl.GetName() == label {
205+
labelExists = true
206+
break
207+
}
208+
}
209+
210+
if !labelExists {
211+
log.Printf("label %s does not exist, skipping application", label)
212+
return
213+
}
214+
215+
_, _, err = client.Issues.AddLabelsToIssue(ctx, owner, repo, issueNum, []string{label})
158216
if err != nil {
159217
log.Printf("failed to apply label %s: %v", label, err)
160218
}

0 commit comments

Comments
 (0)