fix: address review findings
- install.sh: verify SHA-256 checksum before installing binary - install.sh: fallback to ~/.local/bin if /usr/local/bin not writable - install.sh: use sed instead of grep for POSIX-safe JSON parsing - release.yml: remove jq dependency, parse release ID with sed - llm: make temperature configurable via --llm-temperature / LLM_TEMPERATURE - llm: add WithTemperature builder method on Client - llm: omit temperature from request when zero (uses server default)
This commit is contained in:
@@ -38,17 +38,27 @@ jobs:
|
||||
GITEA_URL="${{ github.server_url }}"
|
||||
REPO="${{ github.repository }}"
|
||||
|
||||
# Create release
|
||||
RELEASE_ID=$(curl -sSf -X POST \
|
||||
# Create release (parse ID without jq using grep/sed)
|
||||
RESPONSE=$(curl -sSf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${GITEA_URL}/api/v1/repos/${REPO}/releases" \
|
||||
-d "{\"tag_name\": \"${VERSION}\", \"name\": \"${VERSION}\", \"body\": \"Release ${VERSION}\", \"draft\": false, \"prerelease\": false}" \
|
||||
| jq -r '.id')
|
||||
-d "{\"tag_name\": \"${VERSION}\", \"name\": \"${VERSION}\", \"body\": \"Release ${VERSION}\", \"draft\": false, \"prerelease\": false}")
|
||||
|
||||
RELEASE_ID=$(echo "$RESPONSE" | sed -n 's/.*"id":\([0-9]*\).*/\1/p' | head -1)
|
||||
|
||||
if [ -z "$RELEASE_ID" ]; then
|
||||
echo "Failed to create release" >&2
|
||||
echo "$RESPONSE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Created release ID: ${RELEASE_ID}"
|
||||
|
||||
# Upload each asset
|
||||
for file in dist/*; do
|
||||
filename=$(basename "$file")
|
||||
echo "Uploading ${filename}..."
|
||||
curl -sSf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
@@ -56,4 +66,4 @@ jobs:
|
||||
--data-binary "@${file}"
|
||||
done
|
||||
|
||||
echo "Release ${VERSION} created with $(ls dist/* | wc -l) assets"
|
||||
echo "Release ${VERSION} created with assets"
|
||||
|
||||
@@ -28,6 +28,7 @@ func main() {
|
||||
llmModel := flag.String("llm-model", envOrDefault("LLM_MODEL", ""), "LLM model name")
|
||||
conventionsFile := flag.String("conventions-file", envOrDefault("CONVENTIONS_FILE", ""), "Conventions file path in repo (e.g. CLAUDE.md)")
|
||||
dryRun := flag.Bool("dry-run", false, "Print review to stdout instead of posting")
|
||||
llmTemp := flag.Float64("llm-temperature", envOrDefaultFloat("LLM_TEMPERATURE", 0), "LLM temperature (0 = server default)")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -55,6 +56,9 @@ func main() {
|
||||
// Initialize clients
|
||||
giteaClient := gitea.NewClient(*giteaURL, *reviewerToken)
|
||||
llmClient := llm.NewClient(*llmBaseURL, *llmAPIKey, *llmModel)
|
||||
if *llmTemp > 0 {
|
||||
llmClient.WithTemperature(*llmTemp)
|
||||
}
|
||||
|
||||
log.Printf("Reviewing PR #%d on %s/%s", prNumber, owner, repoName)
|
||||
|
||||
@@ -169,3 +173,13 @@ func envOrDefault(key, defaultVal string) string {
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
func envOrDefaultFloat(key string, defaultVal float64) float64 {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
f, err := strconv.ParseFloat(v, 64)
|
||||
if err == nil {
|
||||
return f
|
||||
}
|
||||
}
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
+44
-4
@@ -6,7 +6,18 @@ set -euo pipefail
|
||||
|
||||
GITEA_URL="${GITEA_URL:-https://gitea.weiker.me}"
|
||||
REPO="rodin/review-bot"
|
||||
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
|
||||
INSTALL_DIR="${INSTALL_DIR:-}"
|
||||
|
||||
# Determine install directory with fallback
|
||||
if [ -z "$INSTALL_DIR" ]; then
|
||||
if [ -w /usr/local/bin ]; then
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
else
|
||||
INSTALL_DIR="${HOME}/.local/bin"
|
||||
mkdir -p "$INSTALL_DIR"
|
||||
echo "Note: Installing to $INSTALL_DIR (add to PATH if needed)"
|
||||
fi
|
||||
fi
|
||||
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
ARCH=$(uname -m)
|
||||
@@ -18,8 +29,8 @@ esac
|
||||
|
||||
BINARY="review-bot-${OS}-${ARCH}"
|
||||
|
||||
# Get latest release tag
|
||||
LATEST=$(curl -sSf "${GITEA_URL}/api/v1/repos/${REPO}/releases?limit=1" | grep -o '"tag_name":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
# Get latest release tag (POSIX-safe parsing without jq)
|
||||
LATEST=$(curl -sSf "${GITEA_URL}/api/v1/repos/${REPO}/releases?limit=1" | sed -n 's/.*"tag_name":"\([^"]*\)".*/\1/p' | head -1)
|
||||
|
||||
if [ -z "$LATEST" ]; then
|
||||
echo "Failed to determine latest release" >&2
|
||||
@@ -29,7 +40,36 @@ fi
|
||||
echo "Installing review-bot ${LATEST} (${OS}/${ARCH})..."
|
||||
|
||||
DOWNLOAD_URL="${GITEA_URL}/${REPO}/releases/download/${LATEST}/${BINARY}"
|
||||
curl -sSfL -o "${INSTALL_DIR}/review-bot" "$DOWNLOAD_URL"
|
||||
CHECKSUM_URL="${GITEA_URL}/${REPO}/releases/download/${LATEST}/checksums.txt"
|
||||
|
||||
# Download binary and checksums
|
||||
TMPDIR=$(mktemp -d)
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
curl -sSfL -o "${TMPDIR}/${BINARY}" "$DOWNLOAD_URL"
|
||||
curl -sSfL -o "${TMPDIR}/checksums.txt" "$CHECKSUM_URL"
|
||||
|
||||
# Verify checksum
|
||||
cd "$TMPDIR"
|
||||
EXPECTED=$(grep "${BINARY}" checksums.txt | awk '{print $1}')
|
||||
ACTUAL=$(sha256sum "${BINARY}" | awk '{print $1}')
|
||||
|
||||
if [ -z "$EXPECTED" ]; then
|
||||
echo "Error: no checksum found for ${BINARY} in checksums.txt" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$EXPECTED" != "$ACTUAL" ]; then
|
||||
echo "Error: checksum mismatch!" >&2
|
||||
echo " Expected: $EXPECTED" >&2
|
||||
echo " Actual: $ACTUAL" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checksum verified ✓"
|
||||
|
||||
# Install
|
||||
cp "${TMPDIR}/${BINARY}" "${INSTALL_DIR}/review-bot"
|
||||
chmod +x "${INSTALL_DIR}/review-bot"
|
||||
|
||||
echo "Installed review-bot ${LATEST} to ${INSTALL_DIR}/review-bot"
|
||||
|
||||
@@ -14,6 +14,7 @@ type Client struct {
|
||||
BaseURL string
|
||||
APIKey string
|
||||
Model string
|
||||
Temperature float64
|
||||
HTTP *http.Client
|
||||
}
|
||||
|
||||
@@ -27,6 +28,13 @@ func NewClient(baseURL, apiKey, model string) *Client {
|
||||
}
|
||||
}
|
||||
|
||||
// WithTemperature sets the temperature for LLM requests.
|
||||
// If not set (zero value), the server default is used.
|
||||
func (c *Client) WithTemperature(t float64) *Client {
|
||||
c.Temperature = t
|
||||
return c
|
||||
}
|
||||
|
||||
// Message represents a chat message.
|
||||
type Message struct {
|
||||
Role string `json:"role"`
|
||||
@@ -53,6 +61,7 @@ type ChatResponse struct {
|
||||
func (c *Client) Complete(messages []Message) (string, error) {
|
||||
reqBody := ChatRequest{
|
||||
Model: c.Model,
|
||||
Temperature: c.Temperature,
|
||||
Messages: messages,
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user