github.com/Redstoneguy129/cli@v0.0.0-20230211220159-15dca4e91917/internal/db/test/test.go (about)

     1  package test
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"context"
     7  	_ "embed"
     8  	"fmt"
     9  	"io"
    10  	"os"
    11  	"path/filepath"
    12  
    13  	"github.com/Redstoneguy129/cli/internal/utils"
    14  	"github.com/docker/docker/api/types"
    15  	"github.com/spf13/afero"
    16  )
    17  
    18  var (
    19  	//go:embed templates/test.sh
    20  	testScript string
    21  )
    22  
    23  func Run(ctx context.Context, fsys afero.Fs) error {
    24  	// Sanity checks.
    25  	{
    26  		if err := utils.LoadConfigFS(fsys); err != nil {
    27  			return err
    28  		}
    29  
    30  		if err := utils.AssertSupabaseDbIsRunning(); err != nil {
    31  			return err
    32  		}
    33  	}
    34  
    35  	return pgProve(ctx, "/tmp", fsys)
    36  }
    37  
    38  func pgProve(ctx context.Context, dstPath string, fsys afero.Fs) error {
    39  	// Copy tests into database container
    40  	var buf bytes.Buffer
    41  	if err := compress(utils.DbTestsDir, &buf, fsys); err != nil {
    42  		return err
    43  	}
    44  	if err := utils.Docker.CopyToContainer(ctx, utils.DbId, dstPath, &buf, types.CopyToContainerOptions{}); err != nil {
    45  		return err
    46  	}
    47  
    48  	// Passing in script string means command line args must be set manually, ie. "$@"
    49  	args := "set -- " + dstPath + "/" + utils.DbTestsDir + ";"
    50  	// Requires unix path inside container
    51  	cmd := []string{"/bin/bash", "-c", args + testScript}
    52  	out, err := utils.DockerExecOnce(ctx, utils.DbId, nil, cmd)
    53  	fmt.Print(out)
    54  	return err
    55  }
    56  
    57  // Ref 1: https://medium.com/@skdomino/taring-untaring-files-in-go-6b07cf56bc07
    58  // Ref 2: https://gist.github.com/mimoo/25fc9716e0f1353791f5908f94d6e726
    59  func compress(src string, buf io.Writer, fsys afero.Fs) error {
    60  	tw := tar.NewWriter(buf)
    61  
    62  	// walk through every file in the folder
    63  	if err := afero.Walk(fsys, src, func(file string, fi os.FileInfo, err error) error {
    64  		// return on any error
    65  		if err != nil {
    66  			return err
    67  		}
    68  
    69  		// return on non-regular files
    70  		if !fi.Mode().IsRegular() {
    71  			return nil
    72  		}
    73  
    74  		// create a new dir/file header
    75  		header, err := tar.FileInfoHeader(fi, fi.Name())
    76  		if err != nil {
    77  			return err
    78  		}
    79  
    80  		// must provide real name
    81  		header.Name = filepath.ToSlash(file)
    82  
    83  		// write the header
    84  		if err := tw.WriteHeader(header); err != nil {
    85  			return err
    86  		}
    87  
    88  		// open files for taring
    89  		f, err := fsys.Open(file)
    90  		if err != nil {
    91  			return err
    92  		}
    93  
    94  		// copy file data into tar writer
    95  		if _, err := io.Copy(tw, f); err != nil {
    96  			return err
    97  		}
    98  
    99  		// manually close here after each file operation; defering would cause each file close
   100  		// to wait until all operations have completed.
   101  		if err := f.Close(); err != nil {
   102  			return err
   103  		}
   104  
   105  		return nil
   106  	}); err != nil {
   107  		return err
   108  	}
   109  
   110  	// produce tar
   111  	if err := tw.Close(); err != nil {
   112  		return err
   113  	}
   114  	return nil
   115  }