feat: 针对action流水线做了一些优化 #74

Merged
eryajf merged 3 commits from main into main 2025-09-29 14:20:49 +08:00
eryajf commented 2025-09-29 10:23:34 +08:00 (Migrated from github.com)

优化点如下:

  1. 添加upx压缩,使二进制包从原来的11M压缩为3.5M。使镜像从原来的18.9M压缩为11.9M
  2. 构建流水线优化。给构建阶段增加go缓存,将镜像构建步骤拆分。使release构建从原来的58s压缩到45s(增加了压缩步骤的情况下),使镜像构建从原来的6min压缩到49s

Summary by CodeRabbit

  • Performance Improvements

    • Reduced binary size via UPX compression for Linux AMD64 and ARM64 builds, enabling faster downloads and potentially quicker startup.
    • Smaller container images by compressing the built executable during the Docker build.
  • Chores

    • Updated CI to use Go version from the module file and improved dependency caching for more consistent builds.
    • Added UPX installation and compression steps to the build pipeline before packaging artifacts.
优化点如下: 1. 添加upx压缩,使二进制包从原来的`11M`压缩为`3.5M`。使镜像从原来的`18.9M`压缩为`11.9M`。 2. 构建流水线优化。给构建阶段增加go缓存,将镜像构建步骤拆分。使release构建从原来的`58s`压缩到`45s`(增加了压缩步骤的情况下),使镜像构建从原来的`6min`压缩到`49s`。 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Performance Improvements** * Reduced binary size via UPX compression for Linux AMD64 and ARM64 builds, enabling faster downloads and potentially quicker startup. * Smaller container images by compressing the built executable during the Docker build. * **Chores** * Updated CI to use Go version from the module file and improved dependency caching for more consistent builds. * Added UPX installation and compression steps to the build pipeline before packaging artifacts. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2025-09-29 10:23:40 +08:00 (Migrated from github.com)

Walkthrough

The release workflow now installs and uses UPX to compress built binaries for Linux AMD64 and ARM64. Go setup switches to go-version-file with dependency cache path. The Dockerfile installs UPX in the builder stage and compresses the built binary before copying into the final image.

Changes

Cohort / File(s) Summary
Release workflow
.github/workflows/release.yml
Switch Go setup to use go-version-file and cache-dependency-path. Add UPX installation (crazy-max/ghaction-upx@v3, install-only). Insert UPX compression steps after building Linux AMD64/ARM64 binaries and before packaging/uploading.
Docker build
Dockerfile
In builder stage, install upx during module download/setup and run upx -9 on the built hubproxy binary prior to copying to the final image. No stage removals or CMD changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer
  participant GH as GitHub Actions (release)
  participant Go as Go Toolchain Setup
  participant UPX as UPX Installer
  participant BLD as Build Steps
  participant CMP as UPX Compression
  participant PKG as Packaging/Upload

  Dev->>GH: Trigger release workflow
  GH->>Go: Setup via go-version-file<br/>(with dependency cache)
  GH->>UPX: Install UPX (install-only)
  GH->>BLD: Build Linux AMD64 binary
  GH->>CMP: Compress AMD64 binary with UPX
  GH->>BLD: Build Linux ARM64 binary
  GH->>CMP: Compress ARM64 binary with UPX
  GH->>PKG: Package and upload artifacts
  note over CMP,PKG: Compression occurs before packaging
sequenceDiagram
  autonumber
  participant CLI as Docker Build
  participant B as Builder Stage
  participant U as UPX
  participant F as Final Image

  CLI->>B: Restore modules / deps
  B->>U: Install upx
  B->>B: Build hubproxy
  B->>U: upx -9 hubproxy
  B->>F: Copy compressed binary
  note over B,F: Runtime image remains unchanged apart from binary size

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I thump my paws—compress, delight!
UPX nibbles bytes to tight.
Two arches packed, a tidy feat,
Release buns hop with lighter feet.
In Docker burrow, slim and spry—
We ship a carrot-sized binary! 🥕🐇

Pre-merge checks and finishing touches

Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check Inconclusive The provided title “feat: 针对action流水线做了一些优化” correctly reflects that the pull request focuses on enhancing the CI pipeline but uses a generic phrase “一些优化” without specifying the main improvements such as UPX compression and Go caching. Consider refining the title to highlight the key optimizations, for example “feat: 优化 CI 流水线,添加 Go 缓存和 UPX 压缩” to make it more descriptive.
Passed checks (2 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage Passed No functions found in the changes. Docstring coverage check skipped.
Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 780ac14a8f and 198a18508b.

📒 Files selected for processing (1)
  • Dockerfile (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfile

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- walkthrough_start --> ## Walkthrough The release workflow now installs and uses UPX to compress built binaries for Linux AMD64 and ARM64. Go setup switches to go-version-file with dependency cache path. The Dockerfile installs UPX in the builder stage and compresses the built binary before copying into the final image. ## Changes | Cohort / File(s) | Summary | |---|---| | **Release workflow**<br>` .github/workflows/release.yml` | Switch Go setup to use `go-version-file` and `cache-dependency-path`. Add UPX installation (crazy-max/ghaction-upx@v3, install-only). Insert UPX compression steps after building Linux AMD64/ARM64 binaries and before packaging/uploading. | | **Docker build**<br>`Dockerfile` | In builder stage, install `upx` during module download/setup and run `upx -9` on the built `hubproxy` binary prior to copying to the final image. No stage removals or CMD changes. | ## Sequence Diagram(s) ```mermaid sequenceDiagram autonumber actor Dev as Developer participant GH as GitHub Actions (release) participant Go as Go Toolchain Setup participant UPX as UPX Installer participant BLD as Build Steps participant CMP as UPX Compression participant PKG as Packaging/Upload Dev->>GH: Trigger release workflow GH->>Go: Setup via go-version-file<br/>(with dependency cache) GH->>UPX: Install UPX (install-only) GH->>BLD: Build Linux AMD64 binary GH->>CMP: Compress AMD64 binary with UPX GH->>BLD: Build Linux ARM64 binary GH->>CMP: Compress ARM64 binary with UPX GH->>PKG: Package and upload artifacts note over CMP,PKG: Compression occurs before packaging ``` ```mermaid sequenceDiagram autonumber participant CLI as Docker Build participant B as Builder Stage participant U as UPX participant F as Final Image CLI->>B: Restore modules / deps B->>U: Install upx B->>B: Build hubproxy B->>U: upx -9 hubproxy B->>F: Copy compressed binary note over B,F: Runtime image remains unchanged apart from binary size ``` ## Estimated code review effort 🎯 2 (Simple) | ⏱️ ~10 minutes ## Poem > I thump my paws—compress, delight! > UPX nibbles bytes to tight. > Two arches packed, a tidy feat, > Release buns hop with lighter feet. > In Docker burrow, slim and spry— > We ship a carrot-sized binary! 🥕🐇 <!-- walkthrough_end --> <!-- pre_merge_checks_walkthrough_start --> ## Pre-merge checks and finishing touches <details> <summary>❌ Failed checks (1 inconclusive)</summary> | Check name | Status | Explanation | Resolution | | :---------: | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ | | Title Check | ❓ Inconclusive | The provided title “feat: 针对action流水线做了一些优化” correctly reflects that the pull request focuses on enhancing the CI pipeline but uses a generic phrase “一些优化” without specifying the main improvements such as UPX compression and Go caching. | Consider refining the title to highlight the key optimizations, for example “feat: 优化 CI 流水线,添加 Go 缓存和 UPX 压缩” to make it more descriptive. | </details> <details> <summary>✅ Passed checks (2 passed)</summary> | Check name | Status | Explanation | | :----------------: | :------- | :------------------------------------------------------------------- | | Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. | | Docstring Coverage | ✅ Passed | No functions found in the changes. Docstring coverage check skipped. | </details> <!-- pre_merge_checks_walkthrough_end --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing touches</summary> <details> <summary>🧪 Generate unit tests</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Post copyable unit tests in a comment </details> </details> <!-- finishing_touch_checkbox_end --> --- <details> <summary>📜 Recent review details</summary> **Configuration used**: CodeRabbit UI **Review profile**: CHILL **Plan**: Pro <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 780ac14a8fa8e909b6b9ff3fb29aac4e872129a1 and 198a18508b12e06f572678be7d029dde65d43138. </details> <details> <summary>📒 Files selected for processing (1)</summary> * `Dockerfile` (1 hunks) </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary> * Dockerfile </details> </details> <!-- tips_start --> --- Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub> <!-- tips_end --> <!-- internal state start --> <!-- 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 --> <!-- internal state end -->
coderabbitai[bot] (Migrated from github.com) reviewed 2025-09-29 10:28:53 +08:00
coderabbitai[bot] (Migrated from github.com) left a comment

Actionable comments posted: 1

🧹 Nitpick comments (8)
Dockerfile (2)

5-11: Keep CMD aligned with BINARY_NAME; consider non‑root runtime.

  • CMD currently hard‑codes ./hubproxy. If BINARY_NAME changes, the container will 404 at start. Option: use shell form to expand env vars.
  • Consider dropping privileges with a dedicated user.

Apply:

- CMD ["./hubproxy"]
+ # Run as non-root
+ RUN adduser -D -H -u 10001 app && chown -R app:app /root
+ USER app
+ # Use shell form so $BINARY_NAME expands at runtime
+ CMD ["sh","-c","exec ./${BINARY_NAME} \"$@\"","--"]

Optional hardening:

  • Pin base: FROM alpine:3.20
  • Add a .dockerignore to trim context (e.g., ignore .git, src/, node_modules, etc.).

10-11: Ensure prebuilt artifacts exist with a pre-build sanity check. Verified that build/hubproxy/hubproxy-linux-amd64 and build/hubproxy/hubproxy-linux-arm64 are present locally; insert this step in your CI/workflow before the “Build and push Docker image”:

#!/bin/bash
set -euo pipefail
test -f build/hubproxy/${BINARY_NAME}-linux-amd64
test -f build/hubproxy/${BINARY_NAME}-linux-arm64
.github/workflows/docker-ghcr.yml (3)

48-55: Docker layer cache prepared but not used.

You create /tmp/.buildx-cache via actions/cache but don’t pass it to buildx, so it’s a no‑op.

Wire it up and rotate the cache:

       - name: Build and push Docker image
         run: |
-          docker buildx build --push \
+          docker buildx build --push \
+            --cache-from type=local,src=/tmp/.buildx-cache \
+            --cache-to type=local,dest=/tmp/.buildx-cache-new,mode=max \
             --platform linux/amd64,linux/arm64 \
             --tag ghcr.io/${{ env.REPO_LOWER }}:${{ env.VERSION }} \
             --tag ghcr.io/${{ env.REPO_LOWER }}:latest \
-            --build-arg VERSION=${{ env.VERSION }} \
             -f Dockerfile .
+          rm -rf /tmp/.buildx-cache
+          mv /tmp/.buildx-cache-new /tmp/.buildx-cache

Also drop the unused --build-arg VERSION (see next comment).


72-80: Remove unused build arg or plumb it into the image.

--build-arg VERSION=${{ env.VERSION }} is passed, but the Dockerfile has no ARG VERSION or labels using it. Either remove it (simplest) or add ARG VERSION + LABEL org.opencontainers.image.version=$VERSION in the Dockerfile.

Minimal change (remove):

-            --build-arg VERSION=${{ env.VERSION }} \

80-81: GHCR_PUBLIC is not consumed.

Setting GHCR_PUBLIC: true here has no effect. GHCR visibility is managed at the package level or via API; buildx doesn’t read this var.

  • Remove it to avoid confusion; or
  • Add a follow-up step to set package visibility via the GitHub API (requires appropriate scopes).
.github/workflows/release.yml (3)

66-71: Harden builds for reproducibility.

Add -trimpath to strip local paths from binaries.

- CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 .
+ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 .
...
- CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 .
+ CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 .

98-109: Make archives more reproducible across environments.

Set deterministic ownership in tarballs.

- tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-amd64.tar.gz -C linux-amd64 hubproxy
+ tar --owner=0 --group=0 -czf hubproxy-${{ steps.version.outputs.version }}-linux-amd64.tar.gz -C linux-amd64 hubproxy
...
- tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-arm64.tar.gz -C linux-arm64 hubproxy
+ tar --owner=0 --group=0 -czf hubproxy-${{ steps.version.outputs.version }}-linux-arm64.tar.gz -C linux-arm64 hubproxy

62-75: Embed version info into binaries (optional)
Define LDFLAGS with -X flags for version and commit, ensure you cd src (where go.mod lives), then build with go build -trimpath -ldflags. For example:

- name: Build binaries with version info
  run: |
    cd src
    LDFLAGS="-s -w \
      -X github.com/yourorg/yourrepo/cmd/main.version=${{ steps.version.outputs.version }} \
      -X github.com/yourorg/yourrepo/cmd/main.commit=${{ github.sha }}"
    CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="${LDFLAGS}" -o ../build/hubproxy/hubproxy-linux-amd64 .
    CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="${LDFLAGS}" -o ../build/hubproxy/hubproxy-linux-arm64 .

Replace github.com/yourorg/yourrepo/cmd/main with your actual module path.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 714224bd29 and 780ac14a8f.

📒 Files selected for processing (3)
  • .github/workflows/docker-ghcr.yml (1 hunks)
  • .github/workflows/release.yml (3 hunks)
  • Dockerfile (1 hunks)
**Actionable comments posted: 1** <details> <summary>🧹 Nitpick comments (8)</summary><blockquote> <details> <summary>Dockerfile (2)</summary><blockquote> `5-11`: **Keep CMD aligned with BINARY_NAME; consider non‑root runtime.** - CMD currently hard‑codes ./hubproxy. If BINARY_NAME changes, the container will 404 at start. Option: use shell form to expand env vars. - Consider dropping privileges with a dedicated user. Apply: ```diff - CMD ["./hubproxy"] + # Run as non-root + RUN adduser -D -H -u 10001 app && chown -R app:app /root + USER app + # Use shell form so $BINARY_NAME expands at runtime + CMD ["sh","-c","exec ./${BINARY_NAME} \"$@\"","--"] ``` Optional hardening: - Pin base: `FROM alpine:3.20` - Add a .dockerignore to trim context (e.g., ignore .git, src/, node_modules, etc.). --- `10-11`: **Ensure prebuilt artifacts exist with a pre-build sanity check.** Verified that `build/hubproxy/hubproxy-linux-amd64` and `build/hubproxy/hubproxy-linux-arm64` are present locally; insert this step in your CI/workflow before the “Build and push Docker image”: ```shell #!/bin/bash set -euo pipefail test -f build/hubproxy/${BINARY_NAME}-linux-amd64 test -f build/hubproxy/${BINARY_NAME}-linux-arm64 ``` </blockquote></details> <details> <summary>.github/workflows/docker-ghcr.yml (3)</summary><blockquote> `48-55`: **Docker layer cache prepared but not used.** You create `/tmp/.buildx-cache` via actions/cache but don’t pass it to buildx, so it’s a no‑op. Wire it up and rotate the cache: ```diff - name: Build and push Docker image run: | - docker buildx build --push \ + docker buildx build --push \ + --cache-from type=local,src=/tmp/.buildx-cache \ + --cache-to type=local,dest=/tmp/.buildx-cache-new,mode=max \ --platform linux/amd64,linux/arm64 \ --tag ghcr.io/${{ env.REPO_LOWER }}:${{ env.VERSION }} \ --tag ghcr.io/${{ env.REPO_LOWER }}:latest \ - --build-arg VERSION=${{ env.VERSION }} \ -f Dockerfile . + rm -rf /tmp/.buildx-cache + mv /tmp/.buildx-cache-new /tmp/.buildx-cache ``` Also drop the unused `--build-arg VERSION` (see next comment). --- `72-80`: **Remove unused build arg or plumb it into the image.** `--build-arg VERSION=${{ env.VERSION }}` is passed, but the Dockerfile has no `ARG VERSION` or labels using it. Either remove it (simplest) or add `ARG VERSION` + `LABEL org.opencontainers.image.version=$VERSION` in the Dockerfile. Minimal change (remove): ```diff - --build-arg VERSION=${{ env.VERSION }} \ ``` --- `80-81`: **`GHCR_PUBLIC` is not consumed.** Setting `GHCR_PUBLIC: true` here has no effect. GHCR visibility is managed at the package level or via API; buildx doesn’t read this var. - Remove it to avoid confusion; or - Add a follow-up step to set package visibility via the GitHub API (requires appropriate scopes). </blockquote></details> <details> <summary>.github/workflows/release.yml (3)</summary><blockquote> `66-71`: **Harden builds for reproducibility.** Add `-trimpath` to strip local paths from binaries. ```diff - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 . + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 . ... - CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 . + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 . ``` --- `98-109`: **Make archives more reproducible across environments.** Set deterministic ownership in tarballs. ```diff - tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-amd64.tar.gz -C linux-amd64 hubproxy + tar --owner=0 --group=0 -czf hubproxy-${{ steps.version.outputs.version }}-linux-amd64.tar.gz -C linux-amd64 hubproxy ... - tar -czf hubproxy-${{ steps.version.outputs.version }}-linux-arm64.tar.gz -C linux-arm64 hubproxy + tar --owner=0 --group=0 -czf hubproxy-${{ steps.version.outputs.version }}-linux-arm64.tar.gz -C linux-arm64 hubproxy ``` --- `62-75`: **Embed version info into binaries (optional)** Define `LDFLAGS` with `-X` flags for `version` and `commit`, ensure you `cd src` (where `go.mod` lives), then build with `go build -trimpath -ldflags`. For example: ```yaml - name: Build binaries with version info run: | cd src LDFLAGS="-s -w \ -X github.com/yourorg/yourrepo/cmd/main.version=${{ steps.version.outputs.version }} \ -X github.com/yourorg/yourrepo/cmd/main.commit=${{ github.sha }}" CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="${LDFLAGS}" -o ../build/hubproxy/hubproxy-linux-amd64 . CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="${LDFLAGS}" -o ../build/hubproxy/hubproxy-linux-arm64 . ``` Replace `github.com/yourorg/yourrepo/cmd/main` with your actual module path. </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used**: CodeRabbit UI **Review profile**: CHILL **Plan**: Pro <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 714224bd29664892a71c1baa6a6fd06e5f2ba8ce and 780ac14a8fa8e909b6b9ff3fb29aac4e872129a1. </details> <details> <summary>📒 Files selected for processing (3)</summary> * `.github/workflows/docker-ghcr.yml` (1 hunks) * `.github/workflows/release.yml` (3 hunks) * `Dockerfile` (1 hunks) </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
coderabbitai[bot] (Migrated from github.com) commented 2025-09-29 10:28:53 +08:00

⚠️ Potential issue | 🔴 Critical

Build will fail: missing output directory for binaries.

This workflow does not create build/hubproxy/ before go build -o ../build/hubproxy/..., causing “no such file or directory”.

Apply:

       - name: 编译二进制文件
         run: |
-          cd src
+          set -euo pipefail
+          mkdir -p build/hubproxy
+          cd src
           
           # Linux AMD64
-          CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 .
+          CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 .
           
           # Linux ARM64
-          CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 .
+          CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 .
           
           # 压缩二进制文件
           upx -9 ../build/hubproxy/hubproxy-linux-amd64
           upx -9 ../build/hubproxy/hubproxy-linux-arm64
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      - name: 编译二进制文件
        run: |
          set -euo pipefail
          mkdir -p build/hubproxy
          cd src
          
          # Linux AMD64
          CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 .
          
          # Linux ARM64
          CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 .
          
          # 压缩二进制文件
          upx -9 ../build/hubproxy/hubproxy-linux-amd64
          upx -9 ../build/hubproxy/hubproxy-linux-arm64
🤖 Prompt for AI Agents
.github/workflows/docker-ghcr.yml around lines 31 to 44: the workflow runs go
build with -o ../build/hubproxy/... but never ensures that the target directory
exists, causing “no such file or directory”; fix by creating the output
directory before the builds (use a command to create ../build/hubproxy with
parents if missing) so the subsequent go build and upx steps can write into that
directory.
_⚠️ Potential issue_ | _🔴 Critical_ **Build will fail: missing output directory for binaries.** This workflow does not create `build/hubproxy/` before `go build -o ../build/hubproxy/...`, causing “no such file or directory”. Apply: ```diff - name: 编译二进制文件 run: | - cd src + set -euo pipefail + mkdir -p build/hubproxy + cd src # Linux AMD64 - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 . + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 . # Linux ARM64 - CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 . + CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 . # 压缩二进制文件 upx -9 ../build/hubproxy/hubproxy-linux-amd64 upx -9 ../build/hubproxy/hubproxy-linux-arm64 ``` <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion - name: 编译二进制文件 run: | set -euo pipefail mkdir -p build/hubproxy cd src # Linux AMD64 CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-amd64 . # Linux ARM64 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -trimpath -ldflags="-s -w" -o ../build/hubproxy/hubproxy-linux-arm64 . # 压缩二进制文件 upx -9 ../build/hubproxy/hubproxy-linux-amd64 upx -9 ../build/hubproxy/hubproxy-linux-arm64 ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` .github/workflows/docker-ghcr.yml around lines 31 to 44: the workflow runs go build with -o ../build/hubproxy/... but never ensures that the target directory exists, causing “no such file or directory”; fix by creating the output directory before the builds (use a command to create ../build/hubproxy with parents if missing) so the subsequent go build and upx steps can write into that directory. ``` </details> <!-- fingerprinting:phantom:triton:chinchilla --> <!-- This is an auto-generated reply by CodeRabbit -->
eryajf (Migrated from github.com) reviewed 2025-09-29 10:30:16 +08:00
eryajf (Migrated from github.com) commented 2025-09-29 10:30:16 +08:00

实际上不用创建,go build的时候会自动创建。

实际上不用创建,go build的时候会自动创建。
coderabbitai[bot] (Migrated from github.com) reviewed 2025-09-29 10:33:20 +08:00
coderabbitai[bot] (Migrated from github.com) commented 2025-09-29 10:33:20 +08:00
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Test if Go build automatically creates output directories
cd /tmp
mkdir test_go_build
cd test_go_build

# Create a minimal Go program
cat > main.go << 'EOF'
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
EOF

# Initialize go module
go mod init test

# Test 1: Try to build to a non-existent directory path
echo "=== Test 1: Building to non-existent directory ==="
rm -rf nonexistent_dir
go build -o nonexistent_dir/subdir/binary main.go
if [ $? -eq 0 ]; then
    echo "✓ Go build successfully created directory structure"
    ls -la nonexistent_dir/subdir/
else
    echo "✗ Go build failed to create directory structure"
fi

# Test 2: Try with nested directories like in the PR
echo -e "\n=== Test 2: Building to nested path like PR ==="
rm -rf build
go build -o build/hubproxy/test-binary main.go
if [ $? -eq 0 ]; then
    echo "✓ Go build successfully created build/hubproxy/ directory"
    ls -la build/hubproxy/
else
    echo "✗ Go build failed to create build/hubproxy/ directory"
fi

Length of output: 505


🏁 Script executed:

#!/bin/bash
# Fix the Go code and test directory creation behavior
cd /tmp/test_go_build

# Create a proper minimal Go program
cat > main.go << 'EOF'
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
EOF

# Test 1: Try to build to a non-existent directory path
echo "=== Test 1: Building to non-existent directory ==="
rm -rf nonexistent_dir
go build -o nonexistent_dir/subdir/binary main.go
if [ $? -eq 0 ]; then
    echo "✓ Go build successfully created directory structure"
    ls -la nonexistent_dir/subdir/
else
    echo "✗ Go build failed to create directory structure"
    echo "Error details:"
fi

# Test 2: Try with nested directories like in the PR
echo -e "\n=== Test 2: Building to nested path like PR ==="
rm -rf build
go build -o build/hubproxy/test-binary main.go
if [ $? -eq 0 ]; then
    echo "✓ Go build successfully created build/hubproxy/ directory"
    ls -la build/hubproxy/
else
    echo "✗ Go build failed to create build/hubproxy/ directory"
fi

# Test 3: Check what happens with mkdir -p behavior
echo -e "\n=== Test 3: Manual verification of directory creation ==="
rm -rf manual_test
mkdir -p manual_test/deep/nested
echo "Created manual_test/deep/nested with mkdir -p"
ls -la manual_test/deep/

Length of output: 594


🏁 Script executed:

#!/bin/bash
# Check current file content and create the simplest Go program
cd /tmp/test_go_build

echo "=== Current main.go content ==="
cat -n main.go

echo -e "\n=== Creating simpler Go program ==="
cat > simple.go << 'EOF'
package main
func main() {}
EOF

# Test with the simple program
echo -e "\n=== Test: Building simple program to non-existent directory ==="
rm -rf testdir
go build -o testdir/subdir/binary simple.go
build_result=$?

if [ $build_result -eq 0 ]; then
    echo "✓ Go build successfully created directory structure"
    ls -la testdir/subdir/
else
    echo "✗ Go build failed to create directory structure (exit code: $build_result)"
fi

# Test with exact path from PR
echo -e "\n=== Test: Building to exact PR path structure ==="
rm -rf build
go build -o build/hubproxy/test-binary simple.go
build_result2=$?

if [ $build_result2 -eq 0 ]; then
    echo "✓ Go build successfully created build/hubproxy/"
    ls -la build/hubproxy/
else
    echo "✗ Go build failed to create build/hubproxy/ (exit code: $build_result2)"
fi

Length of output: 774


@eryajf You're absolutely right! I apologize for the incorrect suggestion.

I just tested this and confirmed that go build does indeed automatically create the output directory structure when using the -o flag. Both go build -o testdir/subdir/binary and go build -o build/hubproxy/test-binary successfully created the intermediate directories without needing mkdir -p.

Thank you for the correction - my suggestion to add directory creation was unnecessary and would have added redundant steps to the workflow.


✏️ Learnings added
Learnt from: eryajf
PR: sky22333/hubproxy#74
File: .github/workflows/docker-ghcr.yml:31-44
Timestamp: 2025-09-29T02:33:19.173Z
Learning: The `go build` command with `-o` flag automatically creates intermediate directories in the output path, so manual directory creation with `mkdir -p` is not required before building Go binaries.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

<details> <summary>🧩 Analysis chain</summary> 🏁 Script executed: ``` #!/bin/bash # Test if Go build automatically creates output directories cd /tmp mkdir test_go_build cd test_go_build # Create a minimal Go program cat > main.go << 'EOF' package main import "fmt" func main() { fmt.Println("Hello, World!") } EOF # Initialize go module go mod init test # Test 1: Try to build to a non-existent directory path echo "=== Test 1: Building to non-existent directory ===" rm -rf nonexistent_dir go build -o nonexistent_dir/subdir/binary main.go if [ $? -eq 0 ]; then echo "✓ Go build successfully created directory structure" ls -la nonexistent_dir/subdir/ else echo "✗ Go build failed to create directory structure" fi # Test 2: Try with nested directories like in the PR echo -e "\n=== Test 2: Building to nested path like PR ===" rm -rf build go build -o build/hubproxy/test-binary main.go if [ $? -eq 0 ]; then echo "✓ Go build successfully created build/hubproxy/ directory" ls -la build/hubproxy/ else echo "✗ Go build failed to create build/hubproxy/ directory" fi ``` Length of output: 505 --- 🏁 Script executed: ``` #!/bin/bash # Fix the Go code and test directory creation behavior cd /tmp/test_go_build # Create a proper minimal Go program cat > main.go << 'EOF' package main import "fmt" func main() { fmt.Println("Hello, World!") } EOF # Test 1: Try to build to a non-existent directory path echo "=== Test 1: Building to non-existent directory ===" rm -rf nonexistent_dir go build -o nonexistent_dir/subdir/binary main.go if [ $? -eq 0 ]; then echo "✓ Go build successfully created directory structure" ls -la nonexistent_dir/subdir/ else echo "✗ Go build failed to create directory structure" echo "Error details:" fi # Test 2: Try with nested directories like in the PR echo -e "\n=== Test 2: Building to nested path like PR ===" rm -rf build go build -o build/hubproxy/test-binary main.go if [ $? -eq 0 ]; then echo "✓ Go build successfully created build/hubproxy/ directory" ls -la build/hubproxy/ else echo "✗ Go build failed to create build/hubproxy/ directory" fi # Test 3: Check what happens with mkdir -p behavior echo -e "\n=== Test 3: Manual verification of directory creation ===" rm -rf manual_test mkdir -p manual_test/deep/nested echo "Created manual_test/deep/nested with mkdir -p" ls -la manual_test/deep/ ``` Length of output: 594 --- 🏁 Script executed: ``` #!/bin/bash # Check current file content and create the simplest Go program cd /tmp/test_go_build echo "=== Current main.go content ===" cat -n main.go echo -e "\n=== Creating simpler Go program ===" cat > simple.go << 'EOF' package main func main() {} EOF # Test with the simple program echo -e "\n=== Test: Building simple program to non-existent directory ===" rm -rf testdir go build -o testdir/subdir/binary simple.go build_result=$? if [ $build_result -eq 0 ]; then echo "✓ Go build successfully created directory structure" ls -la testdir/subdir/ else echo "✗ Go build failed to create directory structure (exit code: $build_result)" fi # Test with exact path from PR echo -e "\n=== Test: Building to exact PR path structure ===" rm -rf build go build -o build/hubproxy/test-binary simple.go build_result2=$? if [ $build_result2 -eq 0 ]; then echo "✓ Go build successfully created build/hubproxy/" ls -la build/hubproxy/ else echo "✗ Go build failed to create build/hubproxy/ (exit code: $build_result2)" fi ``` Length of output: 774 --- </details> @eryajf You're absolutely right! I apologize for the incorrect suggestion. I just tested this and confirmed that `go build` does indeed automatically create the output directory structure when using the `-o` flag. Both `go build -o testdir/subdir/binary` and `go build -o build/hubproxy/test-binary` successfully created the intermediate directories without needing `mkdir -p`. Thank you for the correction - my suggestion to add directory creation was unnecessary and would have added redundant steps to the workflow. --- <details> <summary>✏️ Learnings added</summary> ``` Learnt from: eryajf PR: sky22333/hubproxy#74 File: .github/workflows/docker-ghcr.yml:31-44 Timestamp: 2025-09-29T02:33:19.173Z Learning: The `go build` command with `-o` flag automatically creates intermediate directories in the output path, so manual directory creation with `mkdir -p` is not required before building Go binaries. ``` > Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure [review instructions](https://docs.coderabbit.ai/guides/review-instructions). You can manage existing learnings in the [app](https://app.coderabbit.ai/learnings). </details> <!-- This is an auto-generated reply by CodeRabbit -->
sky22333 commented 2025-09-29 14:11:40 +08:00 (Migrated from github.com)

@eryajf 感谢大佬PR,docker镜像使用预编译二进制文件的话不方便docker build本地编译,我觉得dockerfile部分保持不变比较好

@eryajf 感谢大佬PR,docker镜像使用预编译二进制文件的话不方便`docker build`本地编译,我觉得`dockerfile`部分保持不变比较好
eryajf commented 2025-09-29 14:13:14 +08:00 (Migrated from github.com)

OK,我调整下

OK,我调整下
eryajf commented 2025-09-29 14:19:18 +08:00 (Migrated from github.com)

已恢复dockerfile

已恢复dockerfile
Sign in to join this conversation.