Add some unit test and dockerfile
This commit is contained in:
parent
1bee169123
commit
0819ae1a71
7 changed files with 474 additions and 3 deletions
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
FROM docker.io/golang:1.24.2-bookworm as build
|
||||||
|
WORKDIR /app
|
||||||
|
# Copy dependencies list
|
||||||
|
COPY ./app/go.mod ./
|
||||||
|
COPY ./app/go.sum ./
|
||||||
|
# Build with optional lambda.norpc tag
|
||||||
|
COPY ./app/main.go ./
|
||||||
|
RUN go build -tags lambda.norpc -o main main.go
|
||||||
|
# Copy artifacts to a clean image
|
||||||
|
FROM public.ecr.aws/lambda/provided:al2023
|
||||||
|
COPY --from=build /app/main ${LAMBDA_TASK_ROOT}
|
||||||
|
ENTRYPOINT [ "main" ]
|
||||||
26
app/go.mod
Normal file
26
app/go.mod
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
module n-daisuke-blog-deployment-source
|
||||||
|
|
||||||
|
go 1.24.2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/aws/aws-lambda-go v1.48.0 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.74 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
|
||||||
|
github.com/aws/smithy-go v1.22.2 // indirect
|
||||||
|
)
|
||||||
40
app/go.sum
Normal file
40
app/go.sum
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
github.com/aws/aws-lambda-go v1.48.0 h1:1aZUYsrJu0yo5fC4z+Rba1KhNImXcJcvHu763BxoyIo=
|
||||||
|
github.com/aws/aws-lambda-go v1.48.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
||||||
|
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs=
|
||||||
|
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.74 h1:+1lc5oMFFHlVBclPXQf/POqlvdpBzjLaN2c3ujDCcZw=
|
||||||
|
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.74/go.mod h1:EiskBoFr4SpYnFIbw8UM7DP7CacQXDHEmJqLI1xpRFI=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1 h1:4nm2G6A4pV9rdlWzGMPv4BNtQp22v1hg3yrtkYpeLl8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.1/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3 h1:BRXS0U76Z8wfF+bnkilA2QwpIch6URlm++yPUt9QPmQ=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.3/go.mod h1:bNXKFFyaiVvWuR6O16h/I1724+aXe/tAkA9/QS01t5k=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY=
|
||||||
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
||||||
|
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||||
|
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||||
170
app/main.go
Normal file
170
app/main.go
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/aws/aws-lambda-go/lambda"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/config"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
RepoURL string
|
||||||
|
RepoBranch string
|
||||||
|
S3Bucket string
|
||||||
|
S3Key string
|
||||||
|
AWSRegion string
|
||||||
|
}
|
||||||
|
|
||||||
|
var commandRunner = exec.Command
|
||||||
|
|
||||||
|
func handleRequest(ctx context.Context, event json.RawMessage) error {
|
||||||
|
// Call your existing process (for example, runDeploymentProcess)
|
||||||
|
if err := runDeploymentProcess(ctx); err != nil {
|
||||||
|
// Log the error; you may also report it via CloudWatch alarms
|
||||||
|
log.Printf("Deployment process failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
lambda.Start(handleRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDeploymentProcess(ctx context.Context) error {
|
||||||
|
|
||||||
|
cfg, err := loadConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Configuration error: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a unique temp directory for this run
|
||||||
|
repoDir, err := os.MkdirTemp("", "repo-*")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error creating temporary directory: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(repoDir)
|
||||||
|
zipFilePath := filepath.Join(repoDir, "source.zip")
|
||||||
|
|
||||||
|
// 1. Clone the repository
|
||||||
|
if err := cloneRepository(ctx, cfg.RepoURL, cfg.RepoBranch, repoDir); err != nil {
|
||||||
|
log.Fatalf("Failure in cloning: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Create a ZIP archive of the repository
|
||||||
|
if err := createZipArchive(ctx, repoDir, zipFilePath); err != nil {
|
||||||
|
log.Fatalf("Failure in creating ZIP archive: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Upload the ZIP file to S3
|
||||||
|
cfg_s3, err := config.LoadDefaultConfig(ctx, config.WithRegion(cfg.AWSRegion))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error loading configuration: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s3Client := s3.NewFromConfig(cfg_s3)
|
||||||
|
uploader := manager.NewUploader(s3Client)
|
||||||
|
if err := uploadToS3WithUploader(ctx, zipFilePath, cfg.S3Bucket, cfg.S3Key, uploader); err != nil {
|
||||||
|
log.Fatalf("Failure in uploading to S3: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadConfig() (*Config, error) {
|
||||||
|
repoURL := os.Getenv("REPO_URL")
|
||||||
|
if repoURL == "" {
|
||||||
|
return nil, fmt.Errorf("REPO_URL environment variable not set")
|
||||||
|
}
|
||||||
|
repoBranch := os.Getenv("REPO_BRANCH")
|
||||||
|
if repoBranch == "" {
|
||||||
|
repoBranch = "main"
|
||||||
|
}
|
||||||
|
s3Bucket := os.Getenv("S3_BUCKET")
|
||||||
|
if s3Bucket == "" {
|
||||||
|
return nil, fmt.Errorf("S3_BUCKET environment variable not set")
|
||||||
|
}
|
||||||
|
s3Key := os.Getenv("S3_KEY")
|
||||||
|
if s3Key == "" {
|
||||||
|
s3Key = "source.zip"
|
||||||
|
}
|
||||||
|
awsRegion := os.Getenv("AWS_REGION")
|
||||||
|
if awsRegion == "" {
|
||||||
|
awsRegion = "ap-northeast-1"
|
||||||
|
}
|
||||||
|
return &Config{
|
||||||
|
RepoURL: repoURL,
|
||||||
|
RepoBranch: repoBranch,
|
||||||
|
S3Bucket: s3Bucket,
|
||||||
|
S3Key: s3Key,
|
||||||
|
AWSRegion: awsRegion,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cloneRepository(_ context.Context, repoURL, repoBranch, repoDir string) error {
|
||||||
|
cloneCmd := commandRunner("git", "clone", "--branch", repoBranch, repoURL, repoDir)
|
||||||
|
cloneCmd.Stdout = os.Stdout
|
||||||
|
cloneCmd.Stderr = os.Stderr
|
||||||
|
fmt.Printf("Cloning repository %s (branch %s)...\n", repoURL, repoBranch)
|
||||||
|
if err := cloneCmd.Run(); err != nil {
|
||||||
|
return fmt.Errorf("error cloning repository: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Repository cloned successfully.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createZipArchive(_ context.Context, repoDir, zipFilePath string) error {
|
||||||
|
zipCmd := commandRunner("zip", "-r", zipFilePath, ".")
|
||||||
|
zipCmd.Dir = repoDir // Change to the cloned repo directory
|
||||||
|
zipCmd.Stdout = os.Stdout
|
||||||
|
zipCmd.Stderr = os.Stderr
|
||||||
|
fmt.Println("Creating ZIP archive of the repository...")
|
||||||
|
if err := zipCmd.Run(); err != nil {
|
||||||
|
return fmt.Errorf("error creating ZIP archive: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("ZIP archive created at %s.\n", zipFilePath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Uploader interface {
|
||||||
|
Upload(ctx context.Context, input *s3.PutObjectInput, opts ...func(*manager.Uploader)) (*manager.UploadOutput, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadToS3WithUploader(ctx context.Context, zipPath, bucket, key string, uploader Uploader) error {
|
||||||
|
|
||||||
|
// Open the ZIP file
|
||||||
|
f, err := os.Open(zipPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error opening ZIP file: %v", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
// Upload the file to S3.
|
||||||
|
fmt.Printf("Uploading %s to s3://%s/%s...\n", zipPath, bucket, key)
|
||||||
|
result, err := uploader.Upload(ctx, &s3.PutObjectInput{
|
||||||
|
Bucket: aws.String(bucket),
|
||||||
|
Key: aws.String(key),
|
||||||
|
Body: f,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to upload file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Successfully uploaded to %s\n", result.Location)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
226
app/main_test.go
Normal file
226
app/main_test.go
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
|
||||||
|
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadConfig_Success(t *testing.T) {
|
||||||
|
// Set up environment variables for the test.
|
||||||
|
os.Setenv("REPO_URL", "https://example.com/repo.git")
|
||||||
|
os.Setenv("REPO_BRANCH", "main")
|
||||||
|
os.Setenv("S3_BUCKET", "my-s3-bucket")
|
||||||
|
os.Setenv("S3_KEY", "source.zip")
|
||||||
|
os.Setenv("AWS_REGION", "ap-northeast-1")
|
||||||
|
|
||||||
|
// Call the function.
|
||||||
|
cfg, err := loadConfig()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the configuration values.
|
||||||
|
if cfg.RepoURL != "https://example.com/repo.git" {
|
||||||
|
t.Errorf("unexpected RepoURL: got %s, want %s", cfg.RepoURL, "https://example.com/repo.git")
|
||||||
|
}
|
||||||
|
if cfg.RepoBranch != "main" {
|
||||||
|
t.Errorf("unexpected RepoBranch: got %s, want %s", cfg.RepoBranch, "main")
|
||||||
|
}
|
||||||
|
if cfg.S3Bucket != "my-s3-bucket" {
|
||||||
|
t.Errorf("unexpected S3Bucket: got %s, want %s", cfg.S3Bucket, "my-s3-bucket")
|
||||||
|
}
|
||||||
|
if cfg.S3Key != "source.zip" {
|
||||||
|
t.Errorf("unexpected S3Key: got %s, want %s", cfg.S3Key, "source.zip")
|
||||||
|
}
|
||||||
|
if cfg.AWSRegion != "ap-northeast-1" {
|
||||||
|
t.Errorf("unexpected AWSRegion: got %s, want %s", cfg.AWSRegion, "ap-northeast-1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig_MissingRepoURL(t *testing.T) {
|
||||||
|
// Clear the REPO_URL environment variable.
|
||||||
|
os.Unsetenv("REPO_URL")
|
||||||
|
|
||||||
|
// Optionally, set up other required variables.
|
||||||
|
os.Setenv("S3_BUCKET", "my-s3-bucket")
|
||||||
|
|
||||||
|
// Call the function.
|
||||||
|
_, err := loadConfig()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error due to missing REPO_URL, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadConfig_MissingS3Bucket(t *testing.T) {
|
||||||
|
// Clear the S3_BUCKET environment variable.
|
||||||
|
os.Unsetenv("S3_BUCKET")
|
||||||
|
|
||||||
|
// Optionally, set up other required variables.
|
||||||
|
os.Setenv("REPO_URL", "https://example.com/repo.git")
|
||||||
|
|
||||||
|
// Call the function.
|
||||||
|
_, err := loadConfig()
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error due to missing S3_BUCKET, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHelperProcess is not a real test. It is invoked as a helper process
|
||||||
|
// when our fake command runner is used.
|
||||||
|
func TestHelperProcess(t *testing.T) {
|
||||||
|
if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
|
||||||
|
// If the variable is not set, this function should do nothing.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// If GO_EXIT_STATUS is set, convert it to an integer.
|
||||||
|
if exitStatus := os.Getenv("GO_EXIT_STATUS"); exitStatus != "" {
|
||||||
|
// You can exit with this status if it's nonzero.
|
||||||
|
// For example, if it's "1", then this simulates a failing command.
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
// Otherwise, simulate success.
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fakeExecCommand returns a function that simulates exec.Command.
|
||||||
|
// The success parameter indicates whether the command should succeed.
|
||||||
|
func fakeExecCommand(success bool) func(name string, arg ...string) *exec.Cmd {
|
||||||
|
return func(name string, arg ...string) *exec.Cmd {
|
||||||
|
// We simulate the command by re-executing the test binary with special flags.
|
||||||
|
// The "--" signals the end of flags for our helper.
|
||||||
|
cs := []string{"-test.run=TestHelperProcess", "--", name}
|
||||||
|
cs = append(cs, arg...)
|
||||||
|
cmd := exec.Command(os.Args[0], cs...)
|
||||||
|
// Set an env variable that tells our TestHelperProcess to run.
|
||||||
|
cmd.Env = []string{"GO_WANT_HELPER_PROCESS=1"}
|
||||||
|
if !success {
|
||||||
|
// Set a value to indicate failure. Our helper can inspect this if desired,
|
||||||
|
// or we can simply exit with a non-zero status.
|
||||||
|
cmd.Env = append(cmd.Env, "GO_EXIT_STATUS=1")
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCloneRepository_Success(t *testing.T) {
|
||||||
|
// Override commandRunner to simulate a successful git clone.
|
||||||
|
originalCommandRunner := commandRunner
|
||||||
|
commandRunner = fakeExecCommand(true)
|
||||||
|
defer func() { commandRunner = originalCommandRunner }()
|
||||||
|
|
||||||
|
// Use a temporary directory for testing.
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
// Call cloneRepository.
|
||||||
|
err := cloneRepository(context.Background(), "https://example.com/repo.git", "main", tempDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected success, got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCloneRepository_Failure(t *testing.T) {
|
||||||
|
// Override commandRunner to simulate a failing git clone.
|
||||||
|
originalCommandRunner := commandRunner
|
||||||
|
commandRunner = fakeExecCommand(false)
|
||||||
|
defer func() { commandRunner = originalCommandRunner }()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
|
||||||
|
// Call cloneRepository expecting an error.
|
||||||
|
err := cloneRepository(context.Background(), "https://example.com/repo.git", "main", tempDir)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCreateZipArchive_Success simulates a successful zip creation.
|
||||||
|
func TestCreateZipArchive_Success(t *testing.T) {
|
||||||
|
// Override the global commandRunner with our fake that simulates success.
|
||||||
|
originalCommandRunner := commandRunner
|
||||||
|
commandRunner = fakeExecCommand(true)
|
||||||
|
defer func() { commandRunner = originalCommandRunner }()
|
||||||
|
|
||||||
|
// Use t.TempDir to create a temporary directory simulating the repo directory.
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
// Define a zip file path within the temp directory.
|
||||||
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
||||||
|
|
||||||
|
// Call createZipArchive.
|
||||||
|
if err := createZipArchive(context.Background(), tempDir, zipFilePath); err != nil {
|
||||||
|
t.Fatalf("expected success, got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCreateZipArchive_Failure simulates a failing zip creation.
|
||||||
|
func TestCreateZipArchive_Failure(t *testing.T) {
|
||||||
|
// Override commandRunner to simulate a command failure.
|
||||||
|
originalCommandRunner := commandRunner
|
||||||
|
commandRunner = fakeExecCommand(false)
|
||||||
|
defer func() { commandRunner = originalCommandRunner }()
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
||||||
|
|
||||||
|
// Call createZipArchive and expect an error.
|
||||||
|
if err := createZipArchive(context.Background(), tempDir, zipFilePath); err == nil {
|
||||||
|
t.Fatal("expected an error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fakeUploader implements the Uploader interface.
|
||||||
|
type fakeUploader struct {
|
||||||
|
success bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeUploader) Upload(ctx context.Context, input *s3.PutObjectInput, opts ...func(*manager.Uploader)) (*manager.UploadOutput, error) {
|
||||||
|
if f.success {
|
||||||
|
// Simulate a successful upload with a fake location.
|
||||||
|
return &manager.UploadOutput{Location: "http://fake-s3/uploaded-file"}, nil
|
||||||
|
}
|
||||||
|
// Simulate a failure.
|
||||||
|
return nil, fmt.Errorf("fake upload error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUploadToS3WithUploader_Success(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
// Create a temporary directory and file to act as the ZIP file.
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
||||||
|
content := []byte("dummy zip content")
|
||||||
|
if err := os.WriteFile(zipFilePath, content, 0644); err != nil {
|
||||||
|
t.Fatalf("failed to create temp zip file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a fake uploader that simulates success.
|
||||||
|
u := &fakeUploader{success: true}
|
||||||
|
|
||||||
|
err := uploadToS3WithUploader(ctx, zipFilePath, "fake-bucket", "source.zip", u)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected success, got error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUploadToS3WithUploader_Failure(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
zipFilePath := filepath.Join(tempDir, "source.zip")
|
||||||
|
content := []byte("dummy zip content")
|
||||||
|
if err := os.WriteFile(zipFilePath, content, 0644); err != nil {
|
||||||
|
t.Fatalf("failed to create temp zip file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a fake uploader that simulates a failure.
|
||||||
|
u := &fakeUploader{success: false}
|
||||||
|
|
||||||
|
err := uploadToS3WithUploader(ctx, zipFilePath, "fake-bucket", "source.zip", u)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected an error, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
3
go.mod
3
go.mod
|
|
@ -1,3 +0,0 @@
|
||||||
module n-daisuke-blog-deployment-source
|
|
||||||
|
|
||||||
go 1.24.2
|
|
||||||
0
main.go
0
main.go
Loading…
Add table
Add a link
Reference in a new issue