-
Notifications
You must be signed in to change notification settings - Fork 0
210 lines (188 loc) · 8.51 KB
/
Copy pathcore-opencode-run.yml
File metadata and controls
210 lines (188 loc) · 8.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
name: Core - Reusable OpenCode Run
on:
workflow_call:
inputs:
run-name:
description: 'Name of the run (e.g., security, safety, performance)'
required: true
type: string
prompt:
description: 'The prompt content to use for the run (mutually exclusive with prompt-file)'
required: false
type: string
prompt-file:
description: 'Path to the prompt file (e.g., .github/prompts/security.prompt.md) (mutually exclusive with prompt)'
required: false
type: string
timeout-minutes:
description: 'Timeout for the run job in minutes'
required: false
type: number
default: 120
model:
description: 'OpenCode model to use for the run'
required: false
type: string
default: 'opencode/big-pickle'
agent:
description: 'Agent to use for OpenCode run'
required: false
type: string
default: 'build'
command:
description: 'Command to use for OpenCode run (alternative to prompt/prompt-file)'
required: false
type: string
runner:
description: 'Runner to use for the job'
required: false
type: string
default: 'ubuntu-latest'
outputs:
results:
description: 'The output results from OpenCode (truncated if too large)'
value: ${{ jobs.run.outputs.results }}
results-truncated:
description: 'Whether the results were truncated due to size'
value: ${{ jobs.run.outputs.results-truncated }}
artifact-name:
description: 'Name of the uploaded artifact containing full results'
value: ${{ jobs.run.outputs.artifact-name }}
env:
OPENCODE_INSTALL_URL: 'https://opencode.ai/install'
MAX_OUTPUT_LINES: 50
jobs:
run:
runs-on: ${{ inputs.runner }}
timeout-minutes: ${{ inputs.timeout-minutes }}
outputs:
results: ${{ steps.process-results.outputs.results }}
results-truncated: ${{ steps.process-results.outputs.results-truncated }}
artifact-name: ${{ steps.process-results.outputs.artifact-name }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
- name: Setup and Install OpenCode
run: |
# Add OpenCode to PATH first
echo "$HOME/.opencode/bin" >> $GITHUB_PATH
# Check if OpenCode is already installed and working
if command -v opencode >/dev/null 2>&1 && opencode --version >/dev/null 2>&1; then
echo "OpenCode is already installed and working"
opencode --version
else
echo "OpenCode not found or not working, installing..."
# Add debug information
echo "System information:"
echo "OS: $(uname -s)"
echo "Arch: $(uname -m)"
echo "Install URL: ${{ env.OPENCODE_INSTALL_URL }}"
# Install with better error handling
if ! curl -fsSL ${{ env.OPENCODE_INSTALL_URL }} | bash; then
echo "ERROR: OpenCode installation failed"
echo "Trying alternative installation method..."
# Try installing specific version as fallback
if ! curl -fsSL ${{ env.OPENCODE_INSTALL_URL }} | bash -s -- --version 1.0.180; then
echo "ERROR: Alternative installation also failed"
exit 1
fi
fi
echo "OpenCode installation completed"
# Verify installation with better error reporting
if ! env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode --version; then
echo "ERROR: OpenCode installation verification failed"
echo "Checking installation directory:"
ls -la "$HOME/.opencode/bin/" || echo "Installation directory not found"
exit 1
fi
fi
- name: Run OpenCode ${{ inputs.run-name }}
run: |
if [ -n "${{ inputs.command }}" ]; then
if [ -n "${{ inputs.prompt }}" ]; then
echo "${{ inputs.prompt }}" | env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode run --command "${{ inputs.command }}" --model "${{ inputs.model }}" --agent "${{ inputs.agent }}" > ${{ inputs.run-name }}-results.txt
elif [ -n "${{ inputs.prompt-file }}" ]; then
PROMPT=$(cat ${{ inputs.prompt-file }})
echo "$PROMPT" | env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode run --command "${{ inputs.command }}" --model "${{ inputs.model }}" --agent "${{ inputs.agent }}" > ${{ inputs.run-name }}-results.txt
else
env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode run --command "${{ inputs.command }}" --model "${{ inputs.model }}" --agent "${{ inputs.agent }}" > ${{ inputs.run-name }}-results.txt
fi
elif [ -n "${{ inputs.prompt }}" ]; then
echo "${{ inputs.prompt }}" | env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode run --model "${{ inputs.model }}" --agent "${{ inputs.agent }}" > ${{ inputs.run-name }}-results.txt
elif [ -n "${{ inputs.prompt-file }}" ]; then
PROMPT=$(cat ${{ inputs.prompt-file }})
echo "$PROMPT" | env -i PATH="$HOME/.opencode/bin:$PATH" HOME="$HOME" GH_TOKEN="$GH_TOKEN" opencode run --model "${{ inputs.model }}" --agent "${{ inputs.agent }}" > ${{ inputs.run-name }}-results.txt
else
echo "Error: At least one of 'command', 'prompt', or 'prompt-file' must be provided" >&2
exit 1
fi
- name: Process results for output
id: process-results
if: always()
run: |
RESULTS_FILE="${{ inputs.run-name }}-results.txt"
ARTIFACT_NAME="${{ inputs.run-name }}-results"
MAX_SIZE=60000 # Leave headroom for workflow-call output encoding overhead.
append_multiline_output() {
local name="$1"
local file="$2"
local delimiter
while true; do
delimiter="opencode_output_$(date +%s%N)_$RANDOM"
if ! grep -qxF "$delimiter" "$file"; then
break
fi
done
{
printf '%s<<%s\n' "$name" "$delimiter"
cat "$file"
printf '\n%s\n' "$delimiter"
} >> "$GITHUB_OUTPUT"
}
# Check if results file exists
if [ -f "$RESULTS_FILE" ]; then
# Get file size in bytes
FILE_SIZE=$(wc -c < "$RESULTS_FILE")
echo "artifact-name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
if [ $FILE_SIZE -gt $MAX_SIZE ]; then
# File is too large, truncate and indicate truncation
echo "results-truncated=true" >> $GITHUB_OUTPUT
# Create truncated version with summary
{
echo "# OpenCode Results (Truncated)"
echo ""
echo "⚠️ **Results were truncated due to size limits. Full results are available in the artifact.**"
echo ""
echo "**File size:** $FILE_SIZE bytes (limit: $MAX_SIZE bytes)"
echo ""
echo "---"
echo ""
head -c $((MAX_SIZE - 1000)) "$RESULTS_FILE"
echo ""
echo ""
echo "..."
echo ""
echo "**[Full results available in artifact: $ARTIFACT_NAME]**"
} > truncated-results.txt
append_multiline_output "results" "truncated-results.txt"
else
# File is small enough, use full content
echo "results-truncated=false" >> $GITHUB_OUTPUT
append_multiline_output "results" "$RESULTS_FILE"
fi
else
# No results file found
echo "results-truncated=false" >> $GITHUB_OUTPUT
echo "results=❌ No results file generated" >> $GITHUB_OUTPUT
echo "artifact-name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
fi
- name: Upload ${{ inputs.run-name }} Results
uses: actions/upload-artifact@v7
if: always()
with:
name: ${{ inputs.run-name }}-results
path: ${{ inputs.run-name }}-results.txt