fix: 修复发布流水线 LFS 资产校验
This commit is contained in:
69
versionctl/projectversion/release_assets.go
Normal file
69
versionctl/projectversion/release_assets.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package projectversion
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var releaseAssetChecks = []releaseAssetCheck{
|
||||
{
|
||||
path: "assets/icon.ico",
|
||||
description: "Windows ICO 图标",
|
||||
magic: []byte{0x00, 0x00, 0x01, 0x00},
|
||||
},
|
||||
{
|
||||
path: "assets/icon.icns",
|
||||
description: "macOS ICNS 图标",
|
||||
magic: []byte("icns"),
|
||||
},
|
||||
{
|
||||
path: "assets/icon.png",
|
||||
description: "PNG 图标",
|
||||
magic: []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a},
|
||||
},
|
||||
{
|
||||
path: "frontend/public/icon.png",
|
||||
description: "前端 PNG 图标",
|
||||
magic: []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a},
|
||||
},
|
||||
}
|
||||
|
||||
var gitLFSPointerPrefix = []byte("version https://git-lfs.github.com/spec/v1")
|
||||
|
||||
type releaseAssetCheck struct {
|
||||
path string
|
||||
description string
|
||||
magic []byte
|
||||
}
|
||||
|
||||
func CheckReleaseAssets(root string) error {
|
||||
var errs []error
|
||||
|
||||
for _, check := range releaseAssetChecks {
|
||||
if err := checkReleaseAsset(root, check); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
func checkReleaseAsset(root string, check releaseAssetCheck) error {
|
||||
content, err := os.ReadFile(filepath.Join(root, check.path))
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s 不可读取: %w", check.path, err)
|
||||
}
|
||||
|
||||
if bytes.HasPrefix(content, gitLFSPointerPrefix) {
|
||||
return fmt.Errorf("%s 是 Git LFS pointer,请先拉取 Git LFS 真实内容", check.path)
|
||||
}
|
||||
|
||||
if !bytes.HasPrefix(content, check.magic) {
|
||||
return fmt.Errorf("%s 不是有效的%s", check.path, check.description)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
58
versionctl/projectversion/release_assets_test.go
Normal file
58
versionctl/projectversion/release_assets_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package projectversion
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCheckReleaseAssets(t *testing.T) {
|
||||
t.Run("valid assets", func(t *testing.T) {
|
||||
root := setupReleaseAssetRoot(t)
|
||||
|
||||
require.NoError(t, CheckReleaseAssets(root))
|
||||
})
|
||||
|
||||
t.Run("lfs pointer", func(t *testing.T) {
|
||||
root := setupReleaseAssetRoot(t)
|
||||
writeReleaseAsset(t, root, "assets/icon.ico", []byte("version https://git-lfs.github.com/spec/v1\noid sha256:abc\nsize 123\n"))
|
||||
|
||||
err := CheckReleaseAssets(root)
|
||||
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "assets/icon.ico 是 Git LFS pointer")
|
||||
})
|
||||
|
||||
t.Run("invalid format", func(t *testing.T) {
|
||||
root := setupReleaseAssetRoot(t)
|
||||
writeReleaseAsset(t, root, "frontend/public/icon.png", []byte("not a png"))
|
||||
|
||||
err := CheckReleaseAssets(root)
|
||||
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "frontend/public/icon.png 不是有效的前端 PNG 图标")
|
||||
})
|
||||
}
|
||||
|
||||
func setupReleaseAssetRoot(t *testing.T) string {
|
||||
t.Helper()
|
||||
|
||||
root := t.TempDir()
|
||||
writeReleaseAsset(t, root, "assets/icon.ico", []byte{0x00, 0x00, 0x01, 0x00, 0x01})
|
||||
writeReleaseAsset(t, root, "assets/icon.icns", []byte("icnsdata"))
|
||||
writeReleaseAsset(t, root, "assets/icon.png", []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00})
|
||||
writeReleaseAsset(t, root, "frontend/public/icon.png", []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00})
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
func writeReleaseAsset(t *testing.T, root, relPath string, content []byte) {
|
||||
t.Helper()
|
||||
|
||||
fullPath := filepath.Join(root, relPath)
|
||||
require.NoError(t, os.MkdirAll(filepath.Dir(fullPath), 0o755))
|
||||
require.NoError(t, os.WriteFile(fullPath, content, 0o600))
|
||||
}
|
||||
Reference in New Issue
Block a user