// SPDX-License-Identifier: AGPL-3.0-only package main import ( "archive/zip" "crypto/sha256" "fmt" "io" "os" "path/filepath" "sort" "strings" "time" ) var skillFiles = []string{ "LICENSE", "SKILL.md", "agents/openai.yaml", "references/authoring.md", "references/workflows.md", } func main() { root, err := filepath.Abs(filepath.Join("skills", "sandwich-hime")) must(err) artifactDir := "artifacts" must(os.MkdirAll(artifactDir, 0o755)) outputPath := filepath.Join(artifactDir, "sandwich-hime-skill-v0.1.0.zip") file, err := os.OpenFile(outputPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644) must(err) archive := zip.NewWriter(file) fixed := time.Date(1980, 1, 1, 0, 0, 0, 0, time.UTC) sort.Strings(skillFiles) for _, relative := range skillFiles { path := filepath.Join(root, filepath.FromSlash(relative)) info, err := os.Lstat(path) must(err) if !info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 { panic("skill archive input is not a regular file: " + relative) } header := &zip.FileHeader{Name: "sandwich-hime/" + relative, Method: zip.Deflate} header.SetModTime(fixed) header.SetMode(0o644) writer, err := archive.CreateHeader(header) must(err) source, err := os.Open(path) must(err) _, copyErr := io.Copy(writer, source) closeErr := source.Close() must(copyErr) must(closeErr) } must(archive.Close()) must(file.Close()) verifyExactTree(root) content, err := os.ReadFile(outputPath) must(err) digest := fmt.Sprintf("%x", sha256.Sum256(content)) must(os.WriteFile(filepath.Join(artifactDir, "sandwich-hime-skill-v0.1.0.zip.sha256"), []byte(digest+" "+filepath.Base(outputPath)+"\n"), 0o644)) fmt.Printf("%s %s\n", digest, outputPath) } func verifyExactTree(root string) { want := make(map[string]bool, len(skillFiles)) for _, file := range skillFiles { want[file] = true } var actual []string must(filepath.WalkDir(root, func(path string, entry os.DirEntry, err error) error { if err != nil { return err } if entry.IsDir() { return nil } relative, err := filepath.Rel(root, path) if err != nil { return err } relative = filepath.ToSlash(relative) actual = append(actual, relative) if !want[relative] { return fmt.Errorf("unexpected skill file: %s", relative) } return nil })) if len(actual) != len(want) { panic(fmt.Sprintf("skill file count = %d, want %d", len(actual), len(want))) } for _, file := range actual { if strings.TrimSpace(file) == "" { panic("empty skill filename") } } } func must(err error) { if err != nil { panic(err) } }