Skip to content

Commit

Permalink
Merge branch 'main' into renovate/actions-setup-go-5.x
Browse files Browse the repository at this point in the history
  • Loading branch information
rohansingh authored Apr 25, 2024
2 parents 6a3a711 + 186eba9 commit fb4eb7c
Show file tree
Hide file tree
Showing 61 changed files with 1,193 additions and 733 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
Expand Down Expand Up @@ -39,7 +39,7 @@ jobs:
go-version: "1.22.2"

- name: Install Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: "16"

Expand All @@ -56,7 +56,7 @@ jobs:
mingw-w64-x86_64-toolchain
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install Linux dependencies
if: matrix.os == 'ubuntu-22.04'
Expand Down Expand Up @@ -151,7 +151,7 @@ jobs:

steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: "0"

Expand All @@ -167,7 +167,7 @@ jobs:
path: build

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v5
with:
distribution: goreleaser-pro
version: v1.12.3
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
Expand Down Expand Up @@ -37,7 +37,7 @@ jobs:
go-version: "1.22.2"

- name: Install Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: "16"

Expand All @@ -54,7 +54,7 @@ jobs:
mingw-w64-x86_64-toolchain
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Install Linux dependencies
if: matrix.os == 'ubuntu-22.04'
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
.DS_Store

# Rendered Apps
examples/*.webp
examples/*.gif
examples/**/*.webp
examples/**/*.gif

# Pixlet Binary
pixlet
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def main():
Render and serve it with:

```console
curl https://raw.githubusercontent.com/tidbyt/pixlet/main/examples/hello_world.star | \
curl https://raw.githubusercontent.com/tidbyt/pixlet/main/examples/hello_world/hello_world.star | \
pixlet serve /dev/stdin
```

Expand Down Expand Up @@ -135,7 +135,7 @@ to show the Bitcoin tracker on your Tidbyt:

```console
# render the bitcoin example
pixlet render examples/bitcoin.star
pixlet render examples/bitcoin/bitcoin.star

# login to your Tidbyt account
pixlet login
Expand All @@ -144,7 +144,7 @@ pixlet login
pixlet devices

# push to your favorite Tidbyt
pixlet push <YOUR DEVICE ID> examples/bitcoin.webp
pixlet push <YOUR DEVICE ID> examples/bitcoin/bitcoin.webp
```

To get the ID for a device, run `pixlet devices`. Alternatively, you can
Expand All @@ -158,8 +158,8 @@ If all goes well, you should see the Bitcoin tracker appear on your Tidbyt:
Pushing an applet to your Tidbyt without an installation ID simply displays your applet one time. If you would like your applet to continously display as part of the rotation, add an installation ID to the push command:

```console
pixlet render examples/bitcoin.star
pixlet push --installation-id <INSTALLATION ID> <YOUR DEVICE ID> examples/bitcoin.webp
pixlet render examples/bitcoin/bitcoin.star
pixlet push --installation-id <INSTALLATION ID> <YOUR DEVICE ID> examples/bitcoin/bitcoin.webp
```

For example, if we set the `installationID` to "Bitcoin", it would appear in the mobile app as follows:
Expand Down
150 changes: 22 additions & 128 deletions bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
package bundle

import (
"archive/tar"
"bytes"
"compress/gzip"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"

"github.com/nlepage/go-tarfs"

"tidbyt.dev/pixlet/manifest"
)
Expand All @@ -26,16 +27,12 @@ const (

// AppBundle represents the unpacked bundle in our system.
type AppBundle struct {
Source []byte
Manifest *manifest.Manifest
Source fs.FS
}

// InitFromPath translates a directory containing an app manifest and source
// into an AppBundle.
func InitFromPath(dir string) (*AppBundle, error) {
// Load manifest
path := filepath.Join(dir, manifest.ManifestFileName)
m, err := os.Open(path)
func FromFS(fs fs.FS) (*AppBundle, error) {
m, err := fs.Open(manifest.ManifestFileName)
if err != nil {
return nil, fmt.Errorf("could not open manifest: %w", err)
}
Expand All @@ -46,140 +43,37 @@ func InitFromPath(dir string) (*AppBundle, error) {
return nil, fmt.Errorf("could not load manifest: %w", err)
}

// Load source
path = filepath.Join(dir, man.FileName)
s, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("could not open app source: %w", err)
}
defer s.Close()

src, err := io.ReadAll(s)
if err != nil {
return nil, fmt.Errorf("could not read app source: %w", err)
}

// Create app bundle struct
return &AppBundle{
Manifest: man,
Source: src,
Source: fs,
}, nil
}

// FromDir translates a directory containing an app manifest and source
// into an AppBundle.
func FromDir(dir string) (*AppBundle, error) {
return FromFS(os.DirFS(dir))
}

// LoadBundle loads a compressed archive into an AppBundle.
func LoadBundle(in io.Reader) (*AppBundle, error) {
gzr, err := gzip.NewReader(in)
if err != nil {
return nil, fmt.Errorf("could not create gzip reader: %w", err)
return nil, fmt.Errorf("creating gzip reader: %w", err)
}
defer gzr.Close()

tr := tar.NewReader(gzr)
ab := &AppBundle{}

for {
header, err := tr.Next()
// read the entire tarball into memory so that we can seek
// around it, and so that the underlying reader can be closed.
var b bytes.Buffer
io.Copy(&b, gzr)

switch {
case err == io.EOF:
// If there are no more files in the bundle, validate and return it.
if ab.Manifest == nil {
return nil, fmt.Errorf("could not find manifest in archive")
}
if ab.Source == nil {
return nil, fmt.Errorf("could not find source in archive")
}
return ab, nil
case err != nil:
// If there is an error, return immediately.
return nil, fmt.Errorf("could not read archive: %w", err)
case header == nil:
// If for some reason we end up with a blank header, continue to the
// next one.
continue
case header.Name == AppSourceName:
// Load the app source.
buff := make([]byte, header.Size)
_, err := io.ReadFull(tr, buff)
if err != nil {
return nil, fmt.Errorf("could not read source from archive: %w", err)
}
ab.Source = buff
case header.Name == manifest.ManifestFileName:
// Load the app manifest.
buff := make([]byte, header.Size)
_, err := io.ReadFull(tr, buff)
if err != nil {
return nil, fmt.Errorf("could not read manifest from archive: %w", err)
}

man, err := manifest.LoadManifest(bytes.NewReader(buff))
if err != nil {
return nil, fmt.Errorf("could not load manifest: %w", err)
}
ab.Manifest = man
}
}
}

// WriteBundleToPath is a helper to be able to write the bundle to a provided
// directory.
func (b *AppBundle) WriteBundleToPath(dir string) error {
path := filepath.Join(dir, AppBundleName)
f, err := os.Create(path)
if err != nil {
return fmt.Errorf("could not create file for bundle: %w", err)
}
defer f.Close()

return b.WriteBundle(f)
}

// WriteBundle writes a compressed archive to the provided writer.
func (ab *AppBundle) WriteBundle(out io.Writer) error {
// Setup writers.
gzw := gzip.NewWriter(out)
defer gzw.Close()

tw := tar.NewWriter(gzw)
defer tw.Close()

// Write manifest.
buff := &bytes.Buffer{}
err := ab.Manifest.WriteManifest(buff)
if err != nil {
return fmt.Errorf("could not write manifest to buffer: %w", err)
}
b := buff.Bytes()

hdr := &tar.Header{
Name: manifest.ManifestFileName,
Mode: 0600,
Size: int64(len(b)),
}
err = tw.WriteHeader(hdr)
if err != nil {
return fmt.Errorf("could not write manifest header: %w", err)
}
_, err = tw.Write(b)
if err != nil {
return fmt.Errorf("could not write manifest to archive: %w", err)
}

// Write source.
hdr = &tar.Header{
Name: AppSourceName,
Mode: 0600,
Size: int64(len(ab.Source)),
}
err = tw.WriteHeader(hdr)
if err != nil {
return fmt.Errorf("could not write source header: %w", err)
}
_, err = tw.Write(ab.Source)
r := bytes.NewReader(b.Bytes())
fs, err := tarfs.New(r)
if err != nil {
return fmt.Errorf("could not write source to archive: %w", err)
return nil, fmt.Errorf("creating tarfs: %w", err)
}

return nil
return FromFS(fs)
}
Loading

0 comments on commit fb4eb7c

Please sign in to comment.