Skip to content

Commit d82d1de

Browse files
committed
add e2e test
1 parent d326282 commit d82d1de

File tree

7 files changed

+299
-0
lines changed

7 files changed

+299
-0
lines changed

.github/workflows/e2e.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: E2E Test Check
2+
on:
3+
pull_request:
4+
branches:
5+
- master
6+
- main
7+
types: [ 'opened', 'synchronize' ]
8+
paths:
9+
- '.github/**'
10+
- '.github/workflows/**'
11+
- '**/*.tf'
12+
13+
jobs:
14+
e2e-check:
15+
# if: github.event.review.state == 'approved' || github.event.review.body == 'approved'
16+
runs-on: ubuntu-latest
17+
name: 'e2e check'
18+
steps:
19+
- name: checkout
20+
uses: actions/checkout@v3
21+
- name: set id
22+
id: set-job-id
23+
uses: ayachensiyuan/get-action-job-id@v1.6
24+
env:
25+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26+
with:
27+
job-name: 'e2e check'
28+
- name: Get pull request info
29+
run: |
30+
echo "repo name is" ${{github.event.pull_request.head.repo.full_name}}
31+
echo "branch is" ${{github.event.pull_request.head.ref}}
32+
echo "The current job id is ${{ steps.set-job-id.outputs.jobId }}"
33+
- name: e2e test
34+
run: |
35+
objectPath="github-action/${{github.repository}}/e2e/Action-${{github.run_number}}-${{github.run_id}}-${{ steps.set-job-id.outputs.jobId }}"
36+
go run scripts/curl_fc_trigger.go ${{github.event.pull_request.head.ref}} ${{github.event.pull_request.head.repo.full_name}} ${objectPath}
37+
go run scripts/e2e_check.go ${objectPath}

.github/workflows/weekly_e2e.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Weekly E2E Test Check
2+
on:
3+
workflow_dispatch:
4+
schedule:
5+
- cron: '0 0 * * 0'
6+
7+
jobs:
8+
weekly-e2e-check:
9+
if: github.repository_owner == 'alibabacloud-automation'
10+
runs-on: ubuntu-latest
11+
permissions: write-all
12+
steps:
13+
- name: checkout
14+
uses: actions/checkout@v3
15+
- name: weekly e2e test
16+
run: |
17+
objectPath="github-action/${{github.repository}}/weekly-e2e/Action-${{github.run_number}}-${{github.run_id}}-${{ steps.set-job-id.outputs.jobId }}"
18+
go run scripts/curl_fc_trigger.go main ${{github.repository}} ${objectPath}
19+
go run scripts/e2e_check.go ${objectPath}
20+
- name: update test record
21+
run: |
22+
git add TestRecord.md
23+
cd .git
24+
sudo chmod -R a+rwX .
25+
sudo find . -type d -exec chmod g+s '{}' +
26+
- name: Commit & Push changes
27+
uses: actions-js/push@master
28+
with:
29+
github_token: ${{ secrets.GITHUB_TOKEN }}
30+
message: 'Update TestRecord'
31+
branch: main

scripts/apply.tftest.hcl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
run "apply" {
2+
command = apply
3+
}

scripts/curl_fc_trigger.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"log"
9+
"math/big"
10+
"net/http"
11+
"os"
12+
"strings"
13+
)
14+
15+
var urlPrefix = "https://terraform-fc-test-for-example-module.oss-ap-southeast-1.aliyuncs.com"
16+
17+
func main() {
18+
if len(os.Args)!=4{
19+
log.Println("[ERROR] invalid args")
20+
return
21+
}
22+
branch := strings.TrimSpace(os.Args[1])
23+
repoName := strings.TrimSpace(os.Args[2])
24+
ossObjectPath := strings.TrimSpace(os.Args[3])
25+
26+
// get trigger url
27+
fcTriggerUrl := urlPrefix + "/fcUrls.json"
28+
response, err := http.Get(fcTriggerUrl)
29+
if err != nil {
30+
log.Println("[ERROR] get fc trigger url failed")
31+
}
32+
defer response.Body.Close()
33+
34+
content, _ := io.ReadAll(response.Body)
35+
var data interface{}
36+
json.Unmarshal(content, &data)
37+
triggerMap := data.(map[string]interface{})
38+
39+
n, _ := rand.Int(rand.Reader, big.NewInt(100))
40+
index := int(n.Int64()) % len(triggerMap)
41+
triggerUrl := triggerMap[fmt.Sprintf("%d", index)]
42+
fmt.Println(triggerUrl)
43+
44+
// curl
45+
client := &http.Client{}
46+
req, err := http.NewRequest("GET", triggerUrl.(string),
47+
nil)
48+
if err != nil {
49+
panic(err)
50+
}
51+
req.Header.Add("X-Fc-Invocation-Type", "Async")
52+
53+
query := req.URL.Query()
54+
query.Add("branch", branch)
55+
query.Add("repo_name", repoName)
56+
query.Add("oss_object_path", ossObjectPath)
57+
req.URL.RawQuery = query.Encode()
58+
59+
if _, err := client.Do(req); err != nil {
60+
log.Printf("[ERROR] fail to trigger fc test, err: %s", err)
61+
}
62+
63+
}

scripts/e2e_check.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"log"
7+
"net/http"
8+
"os"
9+
"strings"
10+
"time"
11+
)
12+
13+
var urlPrefix = "https://terraform-fc-test-for-example-module.oss-ap-southeast-1.aliyuncs.com"
14+
15+
func main() {
16+
ossObjectPath := strings.TrimSpace(os.Args[1])
17+
log.Println("run log path:", ossObjectPath)
18+
runLogFileName := "terraform.run.log"
19+
runResultFileName := "terraform.run.result.log"
20+
runLogUrl := urlPrefix + "/" + ossObjectPath + "/" + runLogFileName
21+
runResultUrl := urlPrefix + "/" + ossObjectPath + "/" + runResultFileName
22+
lastLineNum := 0
23+
deadline := time.Now().Add(time.Duration(24) * time.Hour)
24+
finish := false
25+
exitCode := 0
26+
log.Println(runLogUrl)
27+
for !time.Now().After(deadline) {
28+
runLogResponse, err := http.Get(runLogUrl)
29+
if err != nil || runLogResponse.StatusCode != 200 {
30+
log.Println("waiting for job running...")
31+
time.Sleep(5 * time.Second)
32+
continue
33+
}
34+
defer runLogResponse.Body.Close()
35+
36+
s, er := io.ReadAll(runLogResponse.Body)
37+
if er != nil && fmt.Sprint(er) != "EOF" {
38+
log.Println("[ERROR] reading run log response failed:", err)
39+
}
40+
lineNum := len(s)
41+
if runLogResponse.StatusCode == 200 {
42+
if lineNum > lastLineNum {
43+
fmt.Printf("%s", s[lastLineNum:lineNum])
44+
lastLineNum = lineNum
45+
}
46+
}
47+
if finish {
48+
log.Println("run log path:", ossObjectPath)
49+
log.Println("run log url:", runLogUrl)
50+
if strings.Contains(ossObjectPath, "weekly") {
51+
updateTestRecord(ossObjectPath)
52+
exitCode = 0
53+
}
54+
os.Exit(exitCode)
55+
}
56+
runResultResponse, err := http.Get(runResultUrl)
57+
if err != nil || runResultResponse.StatusCode != 200 {
58+
time.Sleep(5 * time.Second)
59+
continue
60+
}
61+
defer runResultResponse.Body.Close()
62+
runResultContent := make([]byte, 100000)
63+
_, err = runResultResponse.Body.Read(runResultContent)
64+
if err != nil && fmt.Sprint(err) != "EOF" {
65+
log.Println("[ERROR] reading run result response failed:", err)
66+
}
67+
finish = true
68+
if !strings.HasPrefix(string(runResultContent), "PASS") {
69+
log.Println("[ERROR] run result:", string(runResultContent))
70+
exitCode = 1
71+
}
72+
}
73+
log.Println("[ERROR] Timeout: waiting for job finished timeout after 24 hours.")
74+
}
75+
76+
func updateTestRecord(ossObjectPath string) {
77+
currentTestRecordFileName := "TestRecord.md"
78+
currentTestRecordFileUrl := urlPrefix + "/" + ossObjectPath + "/" + currentTestRecordFileName
79+
response, err := http.Get(currentTestRecordFileUrl)
80+
if err != nil {
81+
log.Println("[ERROR] failed to get test record from oss")
82+
return
83+
}
84+
defer response.Body.Close()
85+
data, _ := io.ReadAll(response.Body)
86+
currentTestRecord := string(data) + "\n"
87+
88+
testRecordFileName := "TestRecord.md"
89+
var testRecordFile *os.File
90+
oldTestRecord := ""
91+
if _, err := os.Stat(testRecordFileName); os.IsNotExist(err) {
92+
testRecordFile, err = os.Create(testRecordFileName)
93+
if err != nil {
94+
log.Println("[ERROR] failed to create test record file")
95+
}
96+
} else {
97+
data, err := os.ReadFile(testRecordFileName)
98+
if err != nil {
99+
log.Println("[ERROR] failed to read test record file")
100+
return
101+
}
102+
oldTestRecord = string(data)
103+
104+
testRecordFile, err = os.OpenFile(testRecordFileName, os.O_TRUNC|os.O_RDWR, 0666)
105+
if err != nil {
106+
log.Println("[ERROR] failed to open test record file")
107+
}
108+
}
109+
defer testRecordFile.Close()
110+
111+
currentTestRecord += oldTestRecord
112+
testRecordFile.WriteString(currentTestRecord)
113+
}

scripts/plan.tftest.hcl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
run "plan" {
2+
command = plan
3+
}

scripts/terraform-test.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env sh
2+
3+
planFile=${1}"/scripts/plan.tftest.hcl"
4+
applyFile=${1}"/scripts/apply.tftest.hcl"
5+
6+
terraformVersionFile=${1}"/tfversion.md"
7+
echo "" > $terraformVersionFile
8+
version=""
9+
10+
f=${2}
11+
success=true
12+
echo $f
13+
echo ""
14+
echo "====> Terraform testing in" $f
15+
./terraform -chdir=$f init -upgrade
16+
echo ""
17+
echo "----> Plan Testing"
18+
cp $planFile $f/
19+
./terraform -chdir=$f test test -verbose
20+
if [[ $? -ne 0 ]]; then
21+
success=false
22+
echo -e "\033[31m[ERROR]\033[0m: running terraform test for plan failed."
23+
else
24+
echo ""
25+
echo "----> Apply Testing"
26+
rm -rf $f/plan.tftest.hcl
27+
cp $applyFile $f/
28+
./terraform -chdir=$f test test
29+
if [[ $? -ne 0 ]]; then
30+
success=false
31+
echo -e "\033[31m[ERROR]\033[0m: running terraform test for apply failed."
32+
fi
33+
rm -rf $f/apply.tftest.hcl
34+
fi
35+
36+
version=$(./terraform -chdir=$f version)
37+
row=`echo -e "$version" | sed -n '/^$/='`
38+
if [ -n "$row" ]; then
39+
version=`echo -e "$version" | sed -n "1,${row}p"`
40+
fi
41+
42+
echo -e "### Versions\n" >> $terraformVersionFile
43+
echo -e "${version}" >> $terraformVersionFile
44+
45+
if [[ $success == false ]]; then
46+
exit 1
47+
fi
48+
49+
exit 0

0 commit comments

Comments
 (0)