The 'utf-8' codec error when connecting CumulusCI to Github running on Windows Subsystem for Linux - WSL

I have all my projects and development tools on WSL, and have recently installed  CumulusCI version 3.72.1, I followed the instructions to connect it to my Github account by using a person access token I generated in Github, the command example is “cci service connect github mygithub --username $GITHUB_USERNAME --token $GITHUB_TOKEN ". It seemed all good, but when I ran other cci commands, I got the “'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte” error.

The problem seems to be that CumulusCI cannot store an encryption key on WSL, and after my search online, I realized WSL is not officially supported for CumulusCI, but I managed to find a way to fix the issue, shown in the steps below, it could be a workaround until Salesforce.org fixes this issue on WSL.

Step 1:  Make sure you generate your Github person access token with gist and repo scopes.

person access token

Step 2: Go to Folder “~/.cumulusci/services/github”, you will see a file with .service extension , in my case, it is mygithub.service, and empty the content in this file. Keep this empty file, but DON’T DELETE IT.

CumulusCI github service file

Step 3: Find a python file called “encrypted_file_project_keychain.py” in your CumulusCI installation folder, in my case, it is “~/.local/pipx/venvs/cumulusci/lib/python3.10/site-packages/cumulusci/core/keychain/encrypted_file_project_keychain.py”.

Step 4: Identify the method: “def _load_service_files(self) -> None:” in “encrypted_file_project_keychain.py”, and add the code snippet into it after statement “service_type = item.parent.name”

                if service_type == 'github':
                    # print(config)
                    config = ServiceConfig(
                        {'service_name': 'mygithub', 'username': $GITHUB_USERNAME, 'email': $GITHUB_EMAIL, 'token': $GITHUB_TOKEN, 'Organizations': '', 'scopes': 'gist, repo'}
                    )

Please note: Replace $GITHUB_USERNAME, $GITHUB_EMAIL, $GITHUB_TOKEN with your username, email and person access token. The method should look like the one below:

def _load_service_files(self) -> None:
        """
        Load configured services onto the keychain.
        This method recursively goes through all subdirectories
        in ~/.cumulusci/services looking for .service files to load.
        """
        services_dir = Path(f"{self.global_config_dir}/services")
        for item in services_dir.glob("**/*"):
            if item.suffix == ".service":
                with open(item) as f:
                    config = f.read()
                name = item.name.replace(".service", "")
                service_type = item.parent.name
                if service_type == 'github':
                    # print(config)
                    config = ServiceConfig(
                        {'service_name': 'mygithub', 'username': $GITHUB_USERNAME, 'email': $GITHUB_EMAIL, 'token': $GITHUB_TOKEN, 'Organizations': '', 'scopes': 'gist, repo'}
                    )

                self.set_service(
                    service_type, name, config, save=False, config_encrypted=True
                )

After all the steps above, you can test it by running “cci service list”, and you should be able to see something similar below. Your GitHub account is now connected and the error disappears.

If you have any questions or suggestions, please feel free to contact me.

Previous
Previous

A Python Tool to Upgrade Apex Wrapper Salesforce Metadata API Version

Next
Next

How to replace hardcoded Ids in Metadata during a deployment using SFDX