Syncing Static Sites with Pulumi
Real talk, I still haven't successfully decoupled myself from Digital Ocean (though my Bluehost subscription is finally toast) 🤦♀️ like I said I would, but am starting to deploy more projects using Hetzner and Pulumi.
However, I recently ran into the issue of indicating changes in a resource (my static site folder) to trigger Pulumi to update the resource when I run pulumi up
.
Type Name Plan
pulumi:pulumi:Stack dev-dev
Resources:
7 unchanged
Nothing changes, because there's no way for Pulumi to detect that the underlying resource has changed with the current configuration.
If I was using an Amazon S3 bucket, Azure Blob Storage, or Google Cloud Storage, I could use a Synced Folder in Pulumi as the resource, but since I'm deploying to Hetzner with fewer guardrails, I don't have such niceties.
The approach I settled on was to utilize the most recent commit hash from git as a property to track, so I'm still tied to only updating when deploying committed changes.
I added a helper function get_git_commit_hash
to __main__.py
in my Pulumi project
def get_git_commit_hash(directory):
try:
result = subprocess.run(
["git", "rev-parse", "HEAD"],
capture_output=True,
text=True,
check=True,
cwd=directory,
)
return result.stdout.strip()
except Exception as e:
print(f"Warning: Could not get git commit hash from project: {e}")
return "unknown-commit"
then modified the site_sync
resource to the following:
site_sync = command.local.Command(
"sync-site",
create=pulumi.Output.concat(
"rsync -avz -e 'ssh -i ",
config.require("ssh_private_key_path"),
"' ",
config.require("site_path"),
"/* root@",
server.ipv4_address,
":/var/www/",
config.require("domain"),
"/",
),
environment={"GIT_VERSION": git_commit},
opts=ResourceOptions(depends_on=[site_dir], replace_on_changes=["environment"]),
)
The key changes are adding an environment
kwarg to the Command
resource, and modifying the ResourceOptions
to accept the kwarg for replace_on_changes
.
With those changes, when I run pulumi up
, I now get:
Type Name Plan Info
pulumi:pulumi:Stack dev-dev 1 message
+- └─ command:local:Command sync-site replace [diff: ]
Diagnostics:
pulumi:pulumi:Stack (dev-dev):
CompletedProcess(args=['git', 'rev-parse', 'HEAD'], returncode=0, stdout='8d06eff9390f2ab2701a47cb49fed8b5e8342509\n', stderr='')
Resources:
+-1 to replace
6 unchanged
which indicates that my sync-site resource can be replaced as desired!