website

#astro#js#html#css

git clone https://git.pyrossh.dev/website

木 Personal website of pyrossh. Built with astrojs, shiki, vite.


fa93badpyrossh 2026-08-05T11:32:03+05:30
split cache purge into its own resource, track terraform state
.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" "sync_website" {
87
+ resource "terraform_data" "purge_cache" {
73
88
  triggers_replace = [timestamp()]
74
89
 
75
- depends_on = [cloudflare_r2_bucket.website, terraform_data.build_website]
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
+ }