keeping custom profile fields in the upgrade to an enterprise grid org!
slack won't do it so we gotta....
when you upgrade to Slack Enterprise Grid, they just... don't bring your custom profile fields. or the data in them. which is silly but here we are.
this tool dumps all your custom profile field definitions and user profile data from your old workspace, stores it in sqlite, and then recreates everything in your new enterprise grid org.
N.B.: this uses undocumented API endpoints! it was written to work exactly once! it may be broken by the time you see it, if so send patches?
you need ruby 3.4+ and bundler. then:
bundle installmake a .env file with some slack tokens:
FROM_XOXC_TOKEN=xoxc-...
FROM_XOXD_TOKEN=xoxd-...
FROM_TOKEN=xoxb-...
FROM_URL=https://hackclub.slack.com
TO_XOXC_TOKEN=xoxc-...
TO_XOXD_TOKEN=xoxd-...
TO_TOKEN=xoxb-...
TO_URL=https://wackclub.enterprise.slack.comif you don't know what an xoxd is and where it comes from, you may not be the target audience.
set up the database:
thor db:migratestep 1: dump profile fields
thor profile_fields:dumpgrabs all your custom profile field definitions and saves them to the local db.
step 2: dump user profiles
one at a time, to test:
thor users:dump_single USER_IDthen do all of them:
thor users:dump_allthe dump_all command has a bunch of options because slack's rate limits are brutal:
thor users:dump_all \
--threads=10 \
--profile-rate-limit=90 \
--include-restricted=false \
--force--threads- how many parallel workers (default: 10)--profile-rate-limit- max profile.get calls per minute (default: 90, tier 4 limit is 100)--list-rate-limit- max users.list calls per minute (default: 18, tier 2 limit is 20)--include-restricted- include multi-channel guests (default: false)--include-ultra-restricted- include single-channel guests (default: false)--skip-deleted- skip deactivated users (default: false)--force- re-dump users even if they're already in the db--start-cursor <cursor>- resume pagination if it dies mid-run
once this works, save db.db! stash it away for once you have your shiny new grid org...
step 3: migrate to enterprise grid
easy, right?
step 4: recreate fields on target org
thor profile_fields:pushthis creates the fields, but with all the custom ones permissioned to be set by API.
then, create a mapping from old-workspace internal IDs to new-org internal IDs:
thor profile_fields:pull_mappingsthis matches by label, and is important to make sure profile info ends up in the right columns.
step 5: put that data back where it belongs
try it on one user to see if it works:
thor users:restore_single FROM_USER_ID TO_USER_ID(from and to are the same in a real migration, but could be different in testing?)
if that's all good....
pull the trigger.
thor users:restore_allthis will take an eternity because users.profile.set is heavily ratelimited.
once that's done...
step 6: restore field permissions
we set all the fields to be API-editable in step 4, but that means users can't edit them.
luckily:
thor profile_fields:push_permissionswill set things right.
step 7: cry, take a vacation, and bask in the glory of people having their GitHub links in their profile again.
- your tokens may need more scopes, add more until it works :-)
- you may be trying to set fields on someone more important than you
why?
it doesn't feel right to license this code because it's 99% LLM slop...
...
you can use it if it suits your needs.
signed, your pal nora