fix: Windows deployment — broken symlinks, missing packages, dep scanner false positives (#292)

fix: Windows deployment — broken symlinks, missing packages, dep scanner false positives

- Dockerfile: add pdfplumber, pdf2image, anthropic, poppler-utils, bash to ENABLE_FULL_SKILLS
- Dockerfile: resolve broken git symlinks from Windows clone (core.symlinks=false)
- Dockerfile: strip CRLF from docker-entrypoint.sh at build time
- .gitattributes: enforce LF line endings for shell scripts
- dep_scanner.go: track nested subdirectories + scripts dir basename as local modules
This commit is contained in:
Le Dat authored and GitHub committed 2026-03-20 18:54:45 +07:00
1 parent 11673dabf1
commit c9a484d5d7
3 files changed
+37 -2

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# Ensure shell scripts always use LF line endings (critical for Docker builds on Windows)
*.sh text eol=lf
docker-entrypoint.sh text eol=lf
+19 -2
View File
@@ -52,9 +52,10 @@ RUN set -eux; \
apk add --no-cache docker-cli; \
fi; \
if [ "$ENABLE_FULL_SKILLS" = "true" ]; then \
apk add --no-cache python3 py3-pip nodejs npm pandoc github-cli; \
apk add --no-cache python3 py3-pip nodejs npm pandoc github-cli poppler-utils bash; \
pip3 install --no-cache-dir --break-system-packages \
pypdf openpyxl pandas python-pptx markitdown defusedxml lxml; \
pypdf openpyxl pandas python-pptx markitdown defusedxml lxml \
pdfplumber pdf2image anthropic; \
npm install -g --cache /tmp/npm-cache docx pptxgenjs; \
rm -rf /tmp/npm-cache /root/.cache /var/cache/apk/*; \
else \
@@ -77,6 +78,22 @@ COPY --from=builder /out/pkg-helper /app/pkg-helper
COPY --from=builder /src/migrations/ /app/migrations/
COPY --from=builder /src/skills/ /app/bundled-skills/
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
# Fix Windows git clone issues:
# 1. CRLF line endings in shell scripts (Windows git adds \r)
# 2. Broken symlinks: On Windows (core.symlinks=false), git creates text files
# or skips symlinks entirely. Skills like docx/pptx/xlsx need _shared/office
# module in their scripts/ dir (originally symlinked as scripts/office -> ../../_shared/office).
RUN set -eux; \
sed -i 's/\r$//' /app/docker-entrypoint.sh; \
cd /app/bundled-skills; \
for skill in docx pptx xlsx; do \
if [ -d "${skill}/scripts" ] && [ ! -d "${skill}/scripts/office" ]; then \
rm -f "${skill}/scripts/office"; \
cp -r _shared/office "${skill}/scripts/office"; \
fi; \
done
RUN chmod +x /app/docker-entrypoint.sh && \
chmod 755 /app/pkg-helper && chown root:root /app/pkg-helper
+15
View File
@@ -42,6 +42,8 @@ func scanScriptsDir(scriptsDir string) *SkillManifest {
binaries := make(map[string]bool)
// Track subdirectory names — these are local modules and must never be reported as missing.
localModules := make(map[string]bool)
// The scripts directory itself can be referenced as a module (e.g. "from scripts import utils").
localModules[filepath.Base(scriptsDir)] = true
for _, e := range entries {
if e.IsDir() {
@@ -53,6 +55,19 @@ func scanScriptsDir(scriptsDir string) *SkillManifest {
}
for _, se := range subEntries {
if se.IsDir() {
// Track nested subdirs as local modules too (e.g. office/helpers, office/validators)
// so intra-package imports like "from helpers import ..." don't get falsely reported.
localModules[se.Name()] = true
// Scan files inside nested subdirs
nestedEntries, err := os.ReadDir(filepath.Join(scriptsDir, e.Name(), se.Name()))
if err != nil {
continue
}
for _, ne := range nestedEntries {
if !ne.IsDir() {
scanFile(filepath.Join(scriptsDir, e.Name(), se.Name(), ne.Name()), pyImports, nodeImports, binaries)
}
}
continue
}
scanFile(filepath.Join(scriptsDir, e.Name(), se.Name()), pyImports, nodeImports, binaries)