mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-29 21:38:00 +00:00
170 lines
5.1 KiB
Go
170 lines
5.1 KiB
Go
// Copyright 2017 HootSuite Media Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the License);
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an AS IS BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
// Modified hereafter by contributors to runatlantis/atlantis.
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
type E2ETester struct {
|
|
vcsClient VCSClient
|
|
hookID int64
|
|
cloneDirRoot string
|
|
projectType Project
|
|
}
|
|
|
|
type E2EResult struct {
|
|
projectType string
|
|
pullRequestURL string
|
|
testResult string
|
|
}
|
|
|
|
var testFileData = `
|
|
resource "null_resource" "hello" {
|
|
}
|
|
`
|
|
|
|
// nolint: gosec
|
|
func (t *E2ETester) Start(ctx context.Context) (*E2EResult, error) {
|
|
cloneDir := fmt.Sprintf("%s/%s-test", t.cloneDirRoot, t.projectType.Name)
|
|
branchName := fmt.Sprintf("%s-%s", t.projectType.Name, time.Now().Format("20060102150405"))
|
|
testFileName := fmt.Sprintf("%s.tf", t.projectType.Name)
|
|
e2eResult := &E2EResult{}
|
|
e2eResult.projectType = t.projectType.Name
|
|
|
|
// create the directory and parents if necessary
|
|
log.Printf("creating dir %q", cloneDir)
|
|
if err := os.MkdirAll(cloneDir, 0700); err != nil {
|
|
return e2eResult, fmt.Errorf("failed to create dir %q prior to cloning, attempting to continue: %v", cloneDir, err)
|
|
}
|
|
|
|
err := t.vcsClient.Clone(cloneDir)
|
|
if err != nil {
|
|
return e2eResult, err
|
|
}
|
|
|
|
// checkout a new branch for the project
|
|
log.Printf("checking out branch %q", branchName)
|
|
checkoutCmd := exec.Command("git", "checkout", "-b", branchName)
|
|
checkoutCmd.Dir = cloneDir
|
|
if output, err := checkoutCmd.CombinedOutput(); err != nil {
|
|
return e2eResult, fmt.Errorf("failed to git checkout branch %q: %v: %s", branchName, err, string(output))
|
|
}
|
|
|
|
// write a file for running the tests
|
|
randomData := []byte(testFileData)
|
|
filePath := fmt.Sprintf("%s/%s/%s", cloneDir, t.projectType.Name, testFileName)
|
|
log.Printf("creating file to commit %q", filePath)
|
|
err = os.WriteFile(filePath, randomData, 0644)
|
|
if err != nil {
|
|
return e2eResult, fmt.Errorf("couldn't write file %s: %v", filePath, err)
|
|
}
|
|
|
|
// add the file
|
|
log.Printf("git add file %q", filePath)
|
|
addCmd := exec.Command("git", "add", filePath)
|
|
addCmd.Dir = cloneDir
|
|
if output, err := addCmd.CombinedOutput(); err != nil {
|
|
return e2eResult, fmt.Errorf("failed to git add file %q: %v: %s", filePath, err, string(output))
|
|
}
|
|
|
|
// commit the file
|
|
log.Printf("git commit file %q", filePath)
|
|
commitCmd := exec.Command("git", "commit", "-am", "test commit")
|
|
commitCmd.Dir = cloneDir
|
|
if output, err := commitCmd.CombinedOutput(); err != nil {
|
|
return e2eResult, fmt.Errorf("failed to run git commit in %q: %v: %v", cloneDir, err, string(output))
|
|
}
|
|
|
|
// push the branch to remote
|
|
log.Printf("git push branch %q", branchName)
|
|
pushCmd := exec.Command("git", "push", "origin", branchName)
|
|
pushCmd.Dir = cloneDir
|
|
if output, err := pushCmd.CombinedOutput(); err != nil {
|
|
return e2eResult, fmt.Errorf("failed to git push branch %q: %v: %s", branchName, err, string(output))
|
|
}
|
|
|
|
// create a new pr
|
|
title := fmt.Sprintf("This is a test pull request for atlantis e2e test for %s project type", t.projectType.Name)
|
|
url, pullId, err := t.vcsClient.CreatePullRequest(ctx, title, branchName)
|
|
|
|
if err != nil {
|
|
return e2eResult, err
|
|
}
|
|
|
|
// set pull request url
|
|
e2eResult.pullRequestURL = url
|
|
|
|
log.Printf("created pull request %s", url)
|
|
|
|
// defer closing pull request and delete remote branch
|
|
defer func() {
|
|
err := cleanUp(ctx, t, pullId, branchName)
|
|
if err != nil {
|
|
log.Printf("Failed to cleanup: %v", err)
|
|
}
|
|
}()
|
|
|
|
// wait for atlantis to respond to webhook and autoplan.
|
|
time.Sleep(2 * time.Second)
|
|
|
|
state := "not started"
|
|
// waiting for atlantis run and finish
|
|
maxLoops := 20
|
|
i := 0
|
|
for ; i < maxLoops && t.vcsClient.IsAtlantisInProgress(state); i++ {
|
|
time.Sleep(2 * time.Second)
|
|
state, _ = t.vcsClient.GetAtlantisStatus(ctx, branchName)
|
|
if state == "" {
|
|
log.Println("atlantis run hasn't started")
|
|
continue
|
|
}
|
|
log.Printf("atlantis run is in %s state", state)
|
|
}
|
|
if i == maxLoops {
|
|
state = "timed out"
|
|
}
|
|
|
|
log.Printf("atlantis run finished with status %q", state)
|
|
e2eResult.testResult = state
|
|
// check if atlantis run was a success
|
|
if !t.vcsClient.DidAtlantisSucceed(state) {
|
|
return e2eResult, fmt.Errorf("atlantis run project type %q failed with %q status", t.projectType.Name, state)
|
|
}
|
|
|
|
return e2eResult, nil
|
|
}
|
|
|
|
func cleanUp(ctx context.Context, t *E2ETester, pullRequestNumber int, branchName string) error {
|
|
// clean up
|
|
err := t.vcsClient.ClosePullRequest(ctx, pullRequestNumber)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.Printf("closed pull request %d", pullRequestNumber)
|
|
|
|
err = t.vcsClient.DeleteBranch(ctx, branchName)
|
|
if err != nil {
|
|
return fmt.Errorf("error while deleting branch %s: %v", branchName, err)
|
|
}
|
|
log.Printf("deleted branch %s", branchName)
|
|
|
|
return nil
|
|
}
|