Skip to content

Commit 3e33dac

Browse files
authored
feat: make dest optional and introduce github action test (#1)
* feat: make dest optional and introduce github action test * add docker ignore * rename the binary name * change to non-root user home * provide abs path of binary * pass args to the action * try env key * log raw resp * avoid raw response * ci: trigger job * ci: trigger after swithcing api to public mode
1 parent 5b9aba6 commit 3e33dac

File tree

6 files changed

+111
-25
lines changed

6 files changed

+111
-25
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Test Upload File Action
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- "upload-file/**"
8+
pull_request:
9+
branches: [main]
10+
paths:
11+
- "upload-file/**"
12+
workflow_dispatch:
13+
14+
jobs:
15+
test-upload-file:
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout repository
20+
uses: actions/checkout@v4
21+
22+
- name: Create test file
23+
run: |
24+
cat > test-upload.json << 'EOF'
25+
{
26+
"message": "This is a test file for upload action",
27+
"created_at": "$(date -Iseconds)",
28+
}
29+
EOF
30+
31+
- name: Test Upload File Action
32+
uses: ./upload-file
33+
with:
34+
file_path: test-upload.json
35+
security_agent_api_endpoint: ${{ secrets.SECURITY_AGENT_API_ENDPOINT }}
36+
security_agent_api_key: ${{ secrets.SECURITY_AGENT_API_KEY }}

justfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ test-upload-file-docker:
9191
-v "$(pwd)/test-file.json:/test-file.json:ro" \
9292
-e INPUT_FILE_PATH="/test-file.json" \
9393
-e INPUT_DESTINATION="${INPUT_DESTINATION:-temp-data/test-$(date +%s).json}" \
94-
-e INPUT_SECURITY_AGENT_API_ENDPOINT="${INPUT_SECURITY_AGENT_API_ENDPOINT:-}" \
95-
-e INPUT_SECURITY_AGENT_API_KEY="${INPUT_SECURITY_AGENT_API_KEY:-}" \
94+
-e INPUT_SECURITY_AGENT_API_ENDPOINT="${INPUT_SECURITY_AGENT_API_ENDPOINT}" \
95+
-e INPUT_SECURITY_AGENT_API_KEY="${INPUT_SECURITY_AGENT_API_KEY}" \
96+
--network host \
9697
upload-file-test
9798

9899
echo "--- :: Cleaning up test file"

upload-file/.dockerignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Ignore compiled binaries
2+
upload-file
3+
*.exe
4+
5+
# Ignore common development files
6+
.git
7+
.gitignore
8+
*.log
9+
*.tmp
10+
.DS_Store
11+
Thumbs.db
12+
13+
# Ignore IDE files
14+
.vscode/
15+
.idea/
16+
*.swp
17+
*.swo
18+
19+
# Ignore test files
20+
*_test.go
21+
22+
.env

upload-file/Dockerfile

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ RUN go mod download
1414
COPY . .
1515

1616
# Build the application
17-
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o upload-file .
17+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o upload-file-cmd .
1818

1919
# Runtime stage
2020
FROM alpine:latest
@@ -26,17 +26,18 @@ RUN apk --no-cache add ca-certificates
2626
RUN addgroup -g 1001 -S appgroup && \
2727
adduser -u 1001 -S appuser -G appgroup
2828

29-
# Set working directory
30-
WORKDIR /root/
29+
# Set working directory to a location accessible by appuser
30+
WORKDIR /home/appuser
3131

3232
# Copy the binary from builder stage
33-
COPY --from=builder /app/upload-file .
33+
COPY --from=builder /app/upload-file-cmd .
3434

3535
# Change ownership to non-root user
36-
RUN chown appuser:appgroup upload-file
36+
RUN chown appuser:appgroup upload-file-cmd && \
37+
chmod +x upload-file-cmd
3738

3839
# Switch to non-root user
3940
USER appuser
4041

4142
# Command to run the executable
42-
CMD ["./upload-file"]
43+
CMD ["/home/appuser/upload-file-cmd"]

upload-file/action.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ inputs:
1212
required: true
1313
destination:
1414
description: "Destination path or URL for the upload"
15-
required: true
15+
required: false
1616
security_agent_api_endpoint:
1717
description: "Security Agent API endpoint"
1818
required: true
@@ -23,3 +23,8 @@ inputs:
2323
runs:
2424
using: "docker"
2525
image: "Dockerfile"
26+
env:
27+
INPUT_FILE_PATH: ${{ inputs.file_path }}
28+
INPUT_DESTINATION: ${{ inputs.destination }}
29+
INPUT_SECURITY_AGENT_API_ENDPOINT: ${{ inputs.security_agent_api_endpoint }}
30+
INPUT_SECURITY_AGENT_API_KEY: ${{ inputs.security_agent_api_key }}

upload-file/main.go

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package main
33
import (
44
"bytes"
55
"context"
6+
"crypto/sha256"
7+
"encoding/hex"
68
"fmt"
79
"io"
810
"log"
@@ -24,13 +26,27 @@ func main() {
2426
if filePath == "" {
2527
log.Fatal("file-path input is required")
2628
}
27-
if destination == "" {
28-
log.Fatal("destination input is required")
29+
// Validate that the file path is a JSON file
30+
if filepath.Ext(filePath) != ".json" {
31+
log.Fatalf("file must be a JSON file, got: %s", filePath)
32+
}
33+
34+
if securityAgentAPIEndpoint == "" {
35+
log.Fatal("security-agent-api-endpoint input is required")
2936
}
3037
if securityAgentAPIKey == "" {
3138
log.Fatal("security-agent-api-key input is required")
3239
}
3340

41+
if destination == "" {
42+
// Calculate SHA256 of file contents
43+
hash, err := calculateFileSHA256(filePath)
44+
if err != nil {
45+
log.Fatalf("Failed to calculate file hash: %v", err)
46+
}
47+
destination = "uploads/" + hash + ".json"
48+
}
49+
3450
// Perform the upload
3551
err := uploadFile(filePath, destination, securityAgentAPIEndpoint, securityAgentAPIKey)
3652
if err != nil {
@@ -105,21 +121,8 @@ func getPresignedUploadURL(destination, securityAgentAPIEndpoint, securityAgentA
105121

106122
// Execute the request with raw response capture
107123
var response PresignedUploadResponse
108-
var rawResponse interface{}
109-
110-
// First, try to get the raw response to see what we're actually getting
111-
err := client.Run(ctx, req, &rawResponse)
112-
if err != nil {
113-
log.Printf("GraphQL request failed with error: %v", err)
114-
return "", fmt.Errorf("GraphQL request failed: %v", err)
115-
}
116124

117-
// Log the raw response for debugging
118-
// rawJSON, _ := json.MarshalIndent(rawResponse, "", " ")
119-
// log.Printf("Raw GraphQL response: %s", string(rawJSON))
120-
121-
// Now try to parse into our expected structure
122-
err = client.Run(ctx, req, &response)
125+
err := client.Run(ctx, req, &response)
123126
if err != nil {
124127
log.Printf("Failed to parse GraphQL response into expected structure: %v", err)
125128
return "", fmt.Errorf("GraphQL request failed: %v", err)
@@ -215,3 +218,21 @@ func getContentType(filePath string) string {
215218
return "application/octet-stream"
216219
}
217220
}
221+
222+
// calculateFileSHA256 calculates the SHA256 hash of a file's contents
223+
func calculateFileSHA256(filePath string) (string, error) {
224+
file, err := os.Open(filePath)
225+
if err != nil {
226+
return "", fmt.Errorf("failed to open file: %v", err)
227+
}
228+
defer file.Close()
229+
230+
hasher := sha256.New()
231+
_, err = io.Copy(hasher, file)
232+
if err != nil {
233+
return "", fmt.Errorf("failed to read file for hashing: %v", err)
234+
}
235+
236+
hashBytes := hasher.Sum(nil)
237+
return hex.EncodeToString(hashBytes), nil
238+
}

0 commit comments

Comments
 (0)