website
git clone https://git.pyrossh.dev/website
木 Personal website of pyrossh. Built with astrojs, shiki, vite.
fa93bad
— pyrossh
2026-08-05T11:32:03+05:30
split cache purge into its own resource, track terraform state
- .gitignore +0 -2
- infra/main.tf +18 -4
- infra/terraform.tfstate +192 -0
- infra/terraform.tfstate.backup +161 -0
.gitignore
CHANGED
|
@@ -7,6 +7,4 @@ dist/
|
|
|
7
7
|
playwright-report/
|
|
8
8
|
test-results/
|
|
9
9
|
infra/.terraform/
|
|
10
|
-
infra/*.tfstate
|
|
11
|
-
infra/*.tfstate.*
|
|
12
10
|
infra/terraform.tfvars
|
infra/main.tf
CHANGED
|
@@ -60,6 +60,16 @@ resource "terraform_data" "build_website" {
|
|
|
60
60
|
# access key/secret scoped to this bucket, not the Cloudflare API token used
|
|
61
61
|
# above.
|
|
62
62
|
#
|
|
63
|
+
resource "terraform_data" "sync_website" {
|
|
64
|
+
triggers_replace = [timestamp()]
|
|
65
|
+
|
|
66
|
+
depends_on = [cloudflare_r2_bucket.website, terraform_data.build_website]
|
|
67
|
+
|
|
68
|
+
provisioner "local-exec" {
|
|
69
|
+
command = "rclone sync ${path.module}/../dist website:${cloudflare_r2_bucket.website.name} --checksum --fast-list -P"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
63
73
|
# The custom domain sits behind Cloudflare's edge cache, and by default only
|
|
64
74
|
# static-asset extensions (css/js/images/fonts) are cached there — not HTML.
|
|
65
75
|
# Since the sync reuses the same URLs on every deploy (no content-hashed
|
|
@@ -69,15 +79,19 @@ resource "terraform_data" "build_website" {
|
|
|
69
79
|
# used above to also carry the "Zone > Cache Purge > Purge" permission for
|
|
70
80
|
# this zone — it isn't included in the R2-only scope from the setup steps
|
|
71
81
|
# earlier, so add it to the token if the purge call starts failing with 403.
|
|
82
|
+
#
|
|
83
|
+
# Kept as its own resource (not tacked onto sync_website's command) so a
|
|
84
|
+
# flaky purge call fails independently of the sync — you can tell from the
|
|
85
|
+
# apply output which of the two actually broke, rather than one opaque
|
|
86
|
+
# multi-line script's exit code.
|
|
72
|
-
resource "terraform_data" "
|
|
87
|
+
resource "terraform_data" "purge_cache" {
|
|
73
88
|
triggers_replace = [timestamp()]
|
|
74
89
|
|
|
75
|
-
depends_on = [
|
|
90
|
+
depends_on = [terraform_data.sync_website]
|
|
76
91
|
|
|
77
92
|
provisioner "local-exec" {
|
|
78
93
|
command = <<-EOT
|
|
79
|
-
rclone sync ${path.module}/../dist website:${cloudflare_r2_bucket.website.name} --checksum --fast-list
|
|
80
|
-
curl -sf -X POST "https://api.cloudflare.com/client/v4/zones/${var.cloudflare_zone_id}/purge_cache" \
|
|
94
|
+
curl -sf --retry 3 -X POST "https://api.cloudflare.com/client/v4/zones/${var.cloudflare_zone_id}/purge_cache" \
|
|
81
95
|
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
|
82
96
|
-H "Content-Type: application/json" \
|
|
83
97
|
--data '{"purge_everything": true}'
|
infra/terraform.tfstate
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 4,
|
|
3
|
+
"terraform_version": "1.13.3",
|
|
4
|
+
"serial": 23,
|
|
5
|
+
"lineage": "6cb48eaa-b069-089b-fce3-e277626defab",
|
|
6
|
+
"outputs": {
|
|
7
|
+
"bucket_name": {
|
|
8
|
+
"value": "website",
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"custom_domain_ownership_status": {
|
|
12
|
+
"value": "active",
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"custom_domain_ssl_status": {
|
|
16
|
+
"value": "active",
|
|
17
|
+
"type": "string"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"resources": [
|
|
21
|
+
{
|
|
22
|
+
"mode": "managed",
|
|
23
|
+
"type": "cloudflare_r2_bucket",
|
|
24
|
+
"name": "git",
|
|
25
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
26
|
+
"instances": [
|
|
27
|
+
{
|
|
28
|
+
"schema_version": 500,
|
|
29
|
+
"attributes": {
|
|
30
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
31
|
+
"creation_date": "2026-08-05T05:25:00.950Z",
|
|
32
|
+
"id": "git",
|
|
33
|
+
"jurisdiction": "default",
|
|
34
|
+
"location": "APAC",
|
|
35
|
+
"name": "git",
|
|
36
|
+
"storage_class": "Standard"
|
|
37
|
+
},
|
|
38
|
+
"sensitive_attributes": [],
|
|
39
|
+
"identity_schema_version": 0
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"mode": "managed",
|
|
45
|
+
"type": "cloudflare_r2_bucket",
|
|
46
|
+
"name": "website",
|
|
47
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
48
|
+
"instances": [
|
|
49
|
+
{
|
|
50
|
+
"schema_version": 500,
|
|
51
|
+
"attributes": {
|
|
52
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
53
|
+
"creation_date": "2026-08-05T04:28:25.013Z",
|
|
54
|
+
"id": "website",
|
|
55
|
+
"jurisdiction": "default",
|
|
56
|
+
"location": "APAC",
|
|
57
|
+
"name": "website",
|
|
58
|
+
"storage_class": "Standard"
|
|
59
|
+
},
|
|
60
|
+
"sensitive_attributes": [],
|
|
61
|
+
"identity_schema_version": 0
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"mode": "managed",
|
|
67
|
+
"type": "cloudflare_r2_custom_domain",
|
|
68
|
+
"name": "git",
|
|
69
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
70
|
+
"instances": [
|
|
71
|
+
{
|
|
72
|
+
"schema_version": 500,
|
|
73
|
+
"attributes": {
|
|
74
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
75
|
+
"bucket_name": "git",
|
|
76
|
+
"ciphers": null,
|
|
77
|
+
"domain": "git.pyrossh.dev",
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"jurisdiction": "default",
|
|
80
|
+
"min_tls": null,
|
|
81
|
+
"status": {
|
|
82
|
+
"ownership": "pending",
|
|
83
|
+
"ssl": "initializing"
|
|
84
|
+
},
|
|
85
|
+
"zone_id": "e95a5d8957b75859c814579deebfce33",
|
|
86
|
+
"zone_name": "pyrossh.dev"
|
|
87
|
+
},
|
|
88
|
+
"sensitive_attributes": [],
|
|
89
|
+
"identity_schema_version": 0,
|
|
90
|
+
"dependencies": [
|
|
91
|
+
"cloudflare_r2_bucket.git"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"mode": "managed",
|
|
98
|
+
"type": "cloudflare_r2_custom_domain",
|
|
99
|
+
"name": "website",
|
|
100
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
101
|
+
"instances": [
|
|
102
|
+
{
|
|
103
|
+
"schema_version": 500,
|
|
104
|
+
"attributes": {
|
|
105
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
106
|
+
"bucket_name": "website",
|
|
107
|
+
"ciphers": null,
|
|
108
|
+
"domain": "pyrossh.dev",
|
|
109
|
+
"enabled": true,
|
|
110
|
+
"jurisdiction": "default",
|
|
111
|
+
"min_tls": null,
|
|
112
|
+
"status": {
|
|
113
|
+
"ownership": "active",
|
|
114
|
+
"ssl": "active"
|
|
115
|
+
},
|
|
116
|
+
"zone_id": "e95a5d8957b75859c814579deebfce33",
|
|
117
|
+
"zone_name": "pyrossh.dev"
|
|
118
|
+
},
|
|
119
|
+
"sensitive_attributes": [],
|
|
120
|
+
"identity_schema_version": 0,
|
|
121
|
+
"dependencies": [
|
|
122
|
+
"cloudflare_r2_bucket.website"
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"mode": "managed",
|
|
129
|
+
"type": "terraform_data",
|
|
130
|
+
"name": "build_website",
|
|
131
|
+
"provider": "provider[\"terraform.io/builtin/terraform\"]",
|
|
132
|
+
"instances": [
|
|
133
|
+
{
|
|
134
|
+
"schema_version": 0,
|
|
135
|
+
"attributes": {
|
|
136
|
+
"id": "06e5fdf0-4974-c673-b975-2f3fa99846fc",
|
|
137
|
+
"input": null,
|
|
138
|
+
"output": null,
|
|
139
|
+
"triggers_replace": {
|
|
140
|
+
"value": [
|
|
141
|
+
"2026-08-05T05:36:25Z"
|
|
142
|
+
],
|
|
143
|
+
"type": [
|
|
144
|
+
"tuple",
|
|
145
|
+
[
|
|
146
|
+
"string"
|
|
147
|
+
]
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"sensitive_attributes": [],
|
|
152
|
+
"identity_schema_version": 0
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"mode": "managed",
|
|
158
|
+
"type": "terraform_data",
|
|
159
|
+
"name": "sync_website",
|
|
160
|
+
"provider": "provider[\"terraform.io/builtin/terraform\"]",
|
|
161
|
+
"instances": [
|
|
162
|
+
{
|
|
163
|
+
"status": "tainted",
|
|
164
|
+
"schema_version": 0,
|
|
165
|
+
"attributes": {
|
|
166
|
+
"id": "2036dc20-874b-06df-a0e0-481ee25c8d06",
|
|
167
|
+
"input": null,
|
|
168
|
+
"output": null,
|
|
169
|
+
"triggers_replace": {
|
|
170
|
+
"value": [
|
|
171
|
+
"2026-08-05T05:36:38Z"
|
|
172
|
+
],
|
|
173
|
+
"type": [
|
|
174
|
+
"tuple",
|
|
175
|
+
[
|
|
176
|
+
"string"
|
|
177
|
+
]
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"sensitive_attributes": [],
|
|
182
|
+
"identity_schema_version": 0,
|
|
183
|
+
"dependencies": [
|
|
184
|
+
"cloudflare_r2_bucket.website",
|
|
185
|
+
"terraform_data.build_website"
|
|
186
|
+
]
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
],
|
|
191
|
+
"check_results": null
|
|
192
|
+
}
|
infra/terraform.tfstate.backup
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 4,
|
|
3
|
+
"terraform_version": "1.13.3",
|
|
4
|
+
"serial": 17,
|
|
5
|
+
"lineage": "6cb48eaa-b069-089b-fce3-e277626defab",
|
|
6
|
+
"outputs": {
|
|
7
|
+
"bucket_name": {
|
|
8
|
+
"value": "website",
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"custom_domain_ownership_status": {
|
|
12
|
+
"value": "active",
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"custom_domain_ssl_status": {
|
|
16
|
+
"value": "active",
|
|
17
|
+
"type": "string"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"resources": [
|
|
21
|
+
{
|
|
22
|
+
"mode": "managed",
|
|
23
|
+
"type": "cloudflare_r2_bucket",
|
|
24
|
+
"name": "git",
|
|
25
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
26
|
+
"instances": [
|
|
27
|
+
{
|
|
28
|
+
"schema_version": 500,
|
|
29
|
+
"attributes": {
|
|
30
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
31
|
+
"creation_date": "2026-08-05T05:25:00.950Z",
|
|
32
|
+
"id": "git",
|
|
33
|
+
"jurisdiction": "default",
|
|
34
|
+
"location": "APAC",
|
|
35
|
+
"name": "git",
|
|
36
|
+
"storage_class": "Standard"
|
|
37
|
+
},
|
|
38
|
+
"sensitive_attributes": [],
|
|
39
|
+
"identity_schema_version": 0
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"mode": "managed",
|
|
45
|
+
"type": "cloudflare_r2_bucket",
|
|
46
|
+
"name": "website",
|
|
47
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
48
|
+
"instances": [
|
|
49
|
+
{
|
|
50
|
+
"schema_version": 500,
|
|
51
|
+
"attributes": {
|
|
52
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
53
|
+
"creation_date": "2026-08-05T04:28:25.013Z",
|
|
54
|
+
"id": "website",
|
|
55
|
+
"jurisdiction": "default",
|
|
56
|
+
"location": "APAC",
|
|
57
|
+
"name": "website",
|
|
58
|
+
"storage_class": "Standard"
|
|
59
|
+
},
|
|
60
|
+
"sensitive_attributes": [],
|
|
61
|
+
"identity_schema_version": 0
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"mode": "managed",
|
|
67
|
+
"type": "cloudflare_r2_custom_domain",
|
|
68
|
+
"name": "website",
|
|
69
|
+
"provider": "provider[\"registry.terraform.io/cloudflare/cloudflare\"]",
|
|
70
|
+
"instances": [
|
|
71
|
+
{
|
|
72
|
+
"schema_version": 500,
|
|
73
|
+
"attributes": {
|
|
74
|
+
"account_id": "dfdb8ca4e419990852eb214c5b50bd5e",
|
|
75
|
+
"bucket_name": "website",
|
|
76
|
+
"ciphers": null,
|
|
77
|
+
"domain": "pyrossh.dev",
|
|
78
|
+
"enabled": true,
|
|
79
|
+
"jurisdiction": "default",
|
|
80
|
+
"min_tls": null,
|
|
81
|
+
"status": {
|
|
82
|
+
"ownership": "active",
|
|
83
|
+
"ssl": "active"
|
|
84
|
+
},
|
|
85
|
+
"zone_id": "e95a5d8957b75859c814579deebfce33",
|
|
86
|
+
"zone_name": "pyrossh.dev"
|
|
87
|
+
},
|
|
88
|
+
"sensitive_attributes": [],
|
|
89
|
+
"identity_schema_version": 0,
|
|
90
|
+
"dependencies": [
|
|
91
|
+
"cloudflare_r2_bucket.website"
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"mode": "managed",
|
|
98
|
+
"type": "terraform_data",
|
|
99
|
+
"name": "build_website",
|
|
100
|
+
"provider": "provider[\"terraform.io/builtin/terraform\"]",
|
|
101
|
+
"instances": [
|
|
102
|
+
{
|
|
103
|
+
"schema_version": 0,
|
|
104
|
+
"attributes": {
|
|
105
|
+
"id": "82dcd6f4-f2c5-a69f-b707-8db44fc9f2e8",
|
|
106
|
+
"input": null,
|
|
107
|
+
"output": null,
|
|
108
|
+
"triggers_replace": {
|
|
109
|
+
"value": [
|
|
110
|
+
"2026-08-05T05:24:58Z"
|
|
111
|
+
],
|
|
112
|
+
"type": [
|
|
113
|
+
"tuple",
|
|
114
|
+
[
|
|
115
|
+
"string"
|
|
116
|
+
]
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"sensitive_attributes": [],
|
|
121
|
+
"identity_schema_version": 0
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"mode": "managed",
|
|
127
|
+
"type": "terraform_data",
|
|
128
|
+
"name": "sync_website",
|
|
129
|
+
"provider": "provider[\"terraform.io/builtin/terraform\"]",
|
|
130
|
+
"instances": [
|
|
131
|
+
{
|
|
132
|
+
"status": "tainted",
|
|
133
|
+
"schema_version": 0,
|
|
134
|
+
"attributes": {
|
|
135
|
+
"id": "a7aaeeec-5a16-6c2e-17e4-133b6d69deef",
|
|
136
|
+
"input": null,
|
|
137
|
+
"output": null,
|
|
138
|
+
"triggers_replace": {
|
|
139
|
+
"value": [
|
|
140
|
+
"2026-08-05T05:25:10Z"
|
|
141
|
+
],
|
|
142
|
+
"type": [
|
|
143
|
+
"tuple",
|
|
144
|
+
[
|
|
145
|
+
"string"
|
|
146
|
+
]
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"sensitive_attributes": [],
|
|
151
|
+
"identity_schema_version": 0,
|
|
152
|
+
"dependencies": [
|
|
153
|
+
"cloudflare_r2_bucket.website",
|
|
154
|
+
"terraform_data.build_website"
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"check_results": null
|
|
161
|
+
}
|