profile: allow overriding the profile name
The override exists so a dev install can be named "pro-tacts (dev)" —
Contacts shows CardDAVAccountDescription as the account name, where a
dev instance is otherwise indistinguishable from production.

Assisted-by: GLM-5.3 via pi
change kourolvqkonuxyzlymuxrlnptyqzxlqm
commit d24ae9b7a072c7345b411032a81532e8f58a694b
author Alpha Chen <alpha@kejadlen.dev>
date
parent upxvyxvu
diff --git a/Rakefile b/Rakefile
index 27b4321..1f002c2 100644
--- a/Rakefile
+++ b/Rakefile
@@ -64,13 +64,15 @@ end
 desc "Render the macOS configuration profile (carddav.mobileconfig)"
 task profile: "carddav.mobileconfig"
 
-# Rebuilds when the template changes but not when PRO_TACTS_HOSTNAME does;
-# delete carddav.mobileconfig to force a rerender.
+# Rebuilds when the template changes but not when the environment does
+# (PRO_TACTS_HOSTNAME, PRO_TACTS_PROFILE_NAME); delete carddav.mobileconfig
+# to force a rerender.
 file "carddav.mobileconfig" => "lib/pro_tacts/profile.rb" do |task|
   require "pro_tacts/profile"
 
   File.write(task.name, ProTacts::Profile.render(
-    hostname: ENV.fetch("PRO_TACTS_HOSTNAME")
+    hostname: ENV.fetch("PRO_TACTS_HOSTNAME"),
+    name: ENV.fetch("PRO_TACTS_PROFILE_NAME", "pro-tacts")
   ))
 end
 
@@ -80,7 +82,8 @@ namespace :profile do
     require "pro_tacts/profile"
 
     File.write("carddav.mobileconfig", ProTacts::Profile.render(
-      hostname: ENV.fetch("PRO_TACTS_HOSTNAME")
+      hostname: ENV.fetch("PRO_TACTS_HOSTNAME"),
+      name: ENV.fetch("PRO_TACTS_PROFILE_NAME", "pro-tacts")
     ))
     sh "open", "carddav.mobileconfig"
     sh "open", "x-apple.systempreferences:com.apple.preferences.configurationprofiles"
diff --git a/lib/pro_tacts/profile.rb b/lib/pro_tacts/profile.rb
index a06af58..c58fc03 100644
--- a/lib/pro_tacts/profile.rb
+++ b/lib/pro_tacts/profile.rb
@@ -21,12 +21,13 @@ module ProTacts
     # injects (see ProTacts::TailscaleAuth). They stay in the template
     # because the account form expects the fields; dropping them is
     # untested.
-    #: (hostname: String) -> String
-    def self.render(hostname:)
+    #: (hostname: String, ?name: String) -> String
+    def self.render(hostname:, name: "pro-tacts")
       identifier = "#{IDENTIFIER_PREFIX}-#{unique_hex}"
 
       template % {
         hostname: escape(hostname),
+        name: escape(name),
         identifier:,
         account_identifier: "#{identifier}.account",
         top_level_uuid: uuid,
@@ -65,11 +66,11 @@ module ProTacts
               <key>PayloadUUID</key>
               <string>%{payload_uuid}</string>
               <key>PayloadDisplayName</key>
-              <string>pro-tacts</string>
+              <string>%{name}</string>
               <key>PayloadOrganization</key>
               <string>pro-tacts</string>
               <key>CardDAVAccountDescription</key>
-              <string>pro-tacts</string>
+              <string>%{name}</string>
               <key>CardDAVHostName</key>
               <string>%{hostname}</string>
               <key>CardDAVUsername</key>
@@ -81,7 +82,7 @@ module ProTacts
             </dict>
           </array>
           <key>PayloadDisplayName</key>
-          <string>pro-tacts CardDAV</string>
+          <string>%{name} CardDAV</string>
           <key>PayloadIdentifier</key>
           <string>%{identifier}</string>
           <key>PayloadOrganization</key>
diff --git a/test/pro_tacts/test_profile.rb b/test/pro_tacts/test_profile.rb
index 3eb5bb5..ee9e327 100644
--- a/test/pro_tacts/test_profile.rb
+++ b/test/pro_tacts/test_profile.rb
@@ -24,6 +24,21 @@ class ProfileTest < Minitest::Test
     assert_includes xml, "<string>carddav-dev</string>"
   end
 
+  # The name defaults to plain "pro-tacts"; an override (e.g. "pro-tacts
+  # (dev)") keeps a dev install distinguishable from production, both in
+  # Contacts' account list and in System Settings when both are installed.
+  def test_name_defaults_to_pro_tacts
+    assert_includes render, "<string>pro-tacts</string>"
+  end
+
+  def test_name_can_be_overridden
+    xml = ProTacts::Profile.render(hostname: "example.ts.net", name: "pro-tacts (dev)")
+
+    assert_match(%r{<key>CardDAVAccountDescription</key>\s*<string>pro-tacts \(dev\)</string>}, xml)
+    assert_includes xml, "<string>pro-tacts (dev) CardDAV</string>"
+    assert_includes xml, "<string>example.ts.net</string>"
+  end
+
   def test_enables_ssl
     assert_match(/<key>CardDAVUseSSL<\/key>\s*<true\/>/, render)
   end