Skip to content

Commit 9ed6dc6

Browse files
committed
CI: add action to sync examples from Provider
1 parent 14a13f2 commit 9ed6dc6

File tree

2 files changed

+246
-0
lines changed

2 files changed

+246
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Sync Examples From Provider
2+
on:
3+
workflow_dispatch:
4+
schedule:
5+
- cron: '0 0 * * 5'
6+
7+
jobs:
8+
Sync:
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+
with:
16+
token: ${{ secrets.GITHUB_TOKEN }}
17+
18+
- name: Download Terraform & Terraform-docs
19+
run: |
20+
if [ ! -f /usr/local/bin/terraform ]; then
21+
wget -q https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
22+
unzip terraform_1.6.0_linux_amd64.zip -d /usr/local/bin/
23+
fi
24+
25+
mkdir terraform-docs && cd terraform-docs
26+
curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v0.19.0/terraform-docs-v0.19.0-$(uname)-amd64.tar.gz
27+
tar -xzf terraform-docs.tar.gz
28+
chmod +x terraform-docs
29+
sudo mv terraform-docs /usr/local/bin/
30+
cd ..
31+
rm -rf terraform-docs
32+
terraform-docs version
33+
34+
- name: sync examples
35+
id: sync_examples
36+
run: |
37+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
38+
git config --global user.name "github-actions[bot]"
39+
40+
latestVersion=$(curl -s https://api.github.com/repos/aliyun/terraform-provider-alicloud/releases/latest)
41+
published_date=$(echo $latestVersion | jq '.published_at')
42+
version=$(echo $latestVersion | jq '.tag_name')
43+
echo "version=${version//\"/}" >> $GITHUB_OUTPUT
44+
published_timestamp=$(date -d ${published_date//\"/} +%s)
45+
46+
current_time=$(date +%s)
47+
time_diff=$(( (current_time - published_timestamp) / (60*60*24) ))
48+
49+
if [ "$time_diff" -gt 7 ]; then
50+
echo "no update"
51+
echo "update=false" >> $GITHUB_OUTPUT
52+
else
53+
git clone -b ${version//\"/} https://github.com/aliyun/terraform-provider-alicloud.git terraform-provider-alicloud
54+
go run scripts/sync_examples_from_provider.go ${version//\"/}
55+
bash scripts/doc-generate.sh quickstarts >> /dev/null
56+
rm -rf terraform-provider-alicloud
57+
echo "update=true" >> $GITHUB_OUTPUT
58+
fi
59+
60+
61+
- name: Commit & Push changes
62+
if: steps.sync_examples.outputs.update == 'true'
63+
uses: actions-js/push@master
64+
with:
65+
github_token: ${{ secrets.GITHUB_TOKEN }}
66+
message: 'sync examples from Provider ${{ steps.sync_examples.outputs.version }}'
67+
branch: main
68+
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"regexp"
7+
"strconv"
8+
"strings"
9+
)
10+
11+
const (
12+
changlogPath = "./terraform-provider-alicloud/CHANGELOG.md"
13+
providerDocsPath = "./terraform-provider-alicloud/website/docs/r/"
14+
quickstartsPath = "./quickstarts/"
15+
16+
exampleStart = "```terraform"
17+
exampleEnd = "```"
18+
19+
alicloudProvider = "terraform {\n" +
20+
" required_providers {\n" +
21+
" alicloud = {\n" +
22+
" source = \"aliyun/alicloud\"\n" +
23+
" }\n" +
24+
" }\n" +
25+
"}"
26+
27+
header = "## Introduction\n\nThis example is used to create a `%s` resource.\n\n<!-- BEGIN_TF_DOCS -->\n\n<!-- END_TF_DOCS -->\n"
28+
)
29+
30+
func main() {
31+
32+
if len(os.Args) < 2 {
33+
fmt.Println("please input the provider version")
34+
os.Exit(1)
35+
}
36+
37+
version := os.Args[1]
38+
newResource, err := getNewResource(version)
39+
if err != nil {
40+
fmt.Println(err)
41+
os.Exit(1)
42+
}
43+
44+
resourceDocList := []string{}
45+
files, _ := os.ReadDir(providerDocsPath)
46+
for _, file := range files {
47+
if file.IsDir() {
48+
continue
49+
} else {
50+
resourceDocList = append(resourceDocList, file.Name())
51+
}
52+
}
53+
54+
for _, resourceDoc := range resourceDocList {
55+
doc, err := os.ReadFile(providerDocsPath + resourceDoc)
56+
if err != nil {
57+
fmt.Printf("fail to open file %s. Error: %s\n", resourceDoc, err)
58+
}
59+
docContent := string(doc)
60+
if strings.Contains(docContent, "**DEPRECATED:**") {
61+
continue
62+
}
63+
64+
subcategoryIndex := strings.Index(docContent, "subcategory: ") + len("subcategory: ")
65+
subcategoryEndIndex := strings.Index(docContent[subcategoryIndex:], "\n")
66+
subcategory := docContent[subcategoryIndex : subcategoryIndex+subcategoryEndIndex]
67+
subcategory = strings.ReplaceAll(subcategory, "\"", "")
68+
subcategory = strings.ReplaceAll(subcategory, " ", "_")
69+
subcategory = strings.ReplaceAll(subcategory, "_(", "(")
70+
71+
exampleList := []string{}
72+
for {
73+
index := strings.Index(docContent, exampleStart)
74+
if index == -1 {
75+
break
76+
}
77+
78+
docContent = docContent[index+len(exampleStart):]
79+
endIndex := strings.Index(docContent, exampleEnd)
80+
exampleStr := docContent[:endIndex]
81+
exampleStr = strings.TrimSpace(exampleStr)
82+
exampleList = append(exampleList, exampleStr)
83+
docContent = docContent[endIndex+len(exampleEnd):]
84+
}
85+
86+
resourceName := "alicloud_" + strings.TrimSuffix(resourceDoc, ".html.markdown")
87+
targetFileName := strings.ReplaceAll(strings.ReplaceAll(resourceName, "alicloud", "101"), "_", "-") + "-docs-Example"
88+
examplePath := quickstartsPath + subcategory + "/"
89+
90+
for i, exp := range exampleList {
91+
92+
exampleName := targetFileName
93+
if len(exampleList) != 1 {
94+
if i < 9 {
95+
exampleName += "-0" + strconv.Itoa(i+1)
96+
} else {
97+
exampleName += "-" + strconv.Itoa(i+1)
98+
}
99+
}
100+
exampleName = examplePath + exampleName
101+
102+
_, err := os.Stat(exampleName + "/main.tf")
103+
// the example exists
104+
if err == nil {
105+
expFile, err := os.OpenFile(exampleName+"/main.tf",
106+
os.O_RDWR|os.O_TRUNC, 0644)
107+
if err != nil {
108+
continue
109+
}
110+
expFile.WriteString(exp)
111+
expFile.Close()
112+
}
113+
// the example does not exist
114+
if err != nil && os.IsNotExist(err) {
115+
if _, ok := newResource[resourceName]; !ok {
116+
continue
117+
}
118+
119+
err := os.MkdirAll(exampleName, 0755)
120+
if err != nil {
121+
return
122+
}
123+
124+
expFile, err := os.OpenFile(exampleName+"/main.tf",
125+
os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
126+
if err != nil {
127+
continue
128+
}
129+
expFile.WriteString(exp)
130+
expFile.Close()
131+
132+
providerFile, err := os.OpenFile(exampleName+"/provider.tf",
133+
os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
134+
if err != nil {
135+
continue
136+
}
137+
providerFile.WriteString(alicloudProvider)
138+
providerFile.Close()
139+
140+
headerFile, err := os.OpenFile(exampleName+"/README.md",
141+
os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
142+
if err != nil {
143+
continue
144+
}
145+
headerFile.WriteString(fmt.Sprintf(header, resourceName))
146+
headerFile.Close()
147+
}
148+
}
149+
}
150+
151+
}
152+
153+
func getNewResource(version string) (map[string]struct{}, error) {
154+
newResource := map[string]struct{}{}
155+
content, err := os.ReadFile(changlogPath)
156+
if err != nil {
157+
return nil, err
158+
}
159+
changelog := string(content)
160+
161+
logStart := strings.Index(changelog, strings.TrimPrefix(version, "v"))
162+
logEnd := strings.Index(changelog[logStart:], "##")
163+
164+
latestLog := changelog[logStart : logStart+logEnd]
165+
166+
re := regexp.MustCompile("`(.*?)`")
167+
parts := strings.Split(latestLog, "\n")
168+
for _, v := range parts {
169+
if strings.Contains(v, "**New Resource:**") {
170+
matches := re.FindStringSubmatch(v)
171+
if len(matches) > 1 {
172+
newResource[matches[1]] = struct{}{}
173+
}
174+
}
175+
}
176+
177+
return newResource, nil
178+
}

0 commit comments

Comments
 (0)