Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions tools/sources/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ var assets = map[string]asset{
// refgen reads it to hold the copy to the release it documents.
const stamp = ".release"

// shotName is what an unpacked file may be called: a PNG named as site.spec.ts's shoot() names
// one, and nothing a path could climb out of the directory with.
var shotName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]*\.png$`)
// fileName is what an unpacked file may be called: a PNG named as site.spec.ts's shoot() names
// one, the story's diff as spin's site:diff writes it in text and JSON, and nothing a path could
// climb out of the directory with.
var fileName = regexp.MustCompile(`^([a-z0-9][a-z0-9-]*\.png|diff\.(txt|json))$`)

// ready is whether e's release tag already holds the asset the site takes of it: a bump moves
// to a release only once it does. site-shots.yml puts it there about an hour after Release, and
Expand Down Expand Up @@ -117,9 +118,10 @@ func fetchAsset(ctx context.Context, gh *github.Client, dir string, e versions.E
return os.WriteFile(filepath.Join(dir, stamp), []byte(want), 0o644)
}

// untar is the files of a .tar.gz that holds only PNGs, flat. Anything else in it - a directory,
// a link, another name - is refused rather than skipped: the archive is not this repository's,
// and one that is not what site-shots.yml writes is one to look at.
// untar is the files of a .tar.gz that holds only the screenshots and the story's diff, flat.
// Anything else in it - a directory, a link, another name - is refused rather than skipped: the
// archive is not this repository's, and one that is not what site-shots.yml writes is one to
// look at.
func untar(raw []byte) (map[string][]byte, error) {
gz, err := gzip.NewReader(bytes.NewReader(raw))
if err != nil {
Expand All @@ -139,8 +141,8 @@ func untar(raw []byte) (map[string][]byte, error) {
if h.Typeflag == tar.TypeDir && name == "" {
continue
}
if h.Typeflag != tar.TypeReg || !shotName.MatchString(name) {
return nil, fmt.Errorf("%q is not a PNG at the top of the archive", h.Name)
if h.Typeflag != tar.TypeReg || !fileName.MatchString(name) {
return nil, fmt.Errorf("%q is not a screenshot or the story's diff at the top of the archive", h.Name)
}
if h.Size > 16<<20 {
return nil, fmt.Errorf("%s is %d bytes, more than a screenshot", name, h.Size)
Expand Down
9 changes: 5 additions & 4 deletions tools/sources/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ func spinAt(version string) versions.Entry {
// and pin, and a later run - Sync's task reference, with no token - asks nothing again.
func TestTheReleasesScreenshotsAreUnpackedAndStamped(t *testing.T) {
ctx := context.Background()
gh := releases(t, map[string][]byte{"v20261024.01": tarGz(t, map[string]string{"workspace.png": "one", "./workspaces.png": "two"})})
gh := releases(t, map[string][]byte{"v20261024.01": tarGz(t, map[string]string{"workspace.png": "one", "./workspaces.png": "two", "diff.txt": "A /etc/greeting\n", "diff.json": "{}"})})
dir := filepath.Join(t.TempDir(), "spin-site-shots")
e := spinAt("v20261024.01")
if err := fetchAsset(ctx, gh, dir, e, assets["spin"]); err != nil {
t.Fatal(err)
}
for name, want := range map[string]string{"workspace.png": "one", "workspaces.png": "two", stamp: "v20261024.01 " + e.Pin + "\n"} {
for name, want := range map[string]string{"workspace.png": "one", "workspaces.png": "two", "diff.txt": "A /etc/greeting\n", "diff.json": "{}", stamp: "v20261024.01 " + e.Pin + "\n"} {
if got, err := os.ReadFile(filepath.Join(dir, name)); err != nil || string(got) != want {
t.Errorf("%s = %q, %v; want %q", name, got, err, want)
}
Expand All @@ -108,8 +108,9 @@ func TestScreenshotsThatAreNotTheReleasesFail(t *testing.T) {
}{
{"a release without the asset", "v20261019.02", nil, "gh workflow run site-shots.yml -R spin-stack/spin -f tag=v20261019.02"},
{"a pin that is no release", "main", nil, "which is no release"},
{"an archive with a directory in it", "v20261024.01", tarGz(t, map[string]string{"shots/workspace.png": "x"}), "not a PNG at the top"},
{"an archive that climbs out", "v20261024.01", tarGz(t, map[string]string{"../workspace.png": "x"}), "not a PNG at the top"},
{"an archive with a directory in it", "v20261024.01", tarGz(t, map[string]string{"shots/workspace.png": "x"}), "not a screenshot or the story's diff at the top"},
{"an archive that climbs out", "v20261024.01", tarGz(t, map[string]string{"../workspace.png": "x"}), "not a screenshot or the story's diff at the top"},
{"an archive with another file", "v20261024.01", tarGz(t, map[string]string{"workspace.png": "x", "notes.txt": "x"}), "not a screenshot or the story's diff at the top"},
{"an empty archive", "v20261024.01", tarGz(t, nil), "no screenshot"},
} {
dir := filepath.Join(t.TempDir(), "spin-site-shots")
Expand Down
Loading