Remote iOS Packaging - Manifest File Permissions Wrong

Trying to do some build automation on a Windows Server EC2 instance for packaging iOS using a remote Mac build node. Process works perfectly locally and almost working on the EC2 instance, but for some reason when the EC2 instance download the remote Manifest.xml is doesn’t have access to the file:

UATHelper: Packaging (iOS):     Writing manifest to /Users/remote-user/UE4/Builds/EC2-ID/Z/W/Project/Intermediate/Remote/Project/IOS/Development/Manifest.xml

...

UATHelper: Packaging (iOS):   [Remote] Downloading Z:\W\Project\Intermediate\Remote\Project\IOS\Development\Manifest.xml
UATHelper: Packaging (iOS):   Access to the path 'Z:\W\Project\Intermediate\Remote\Project\IOS\Development\Manifest.xml' is denied.
UATHelper: Packaging (iOS):   [Remote] Downloading build products

Any ideas how to fix the file permissions?

Continued digging into this more and it looks like the permissions on the files being downloaded from the iOS node are being corrupted. Using an EC2 build node connected to the primary node via CYGWIN so I’m assuming some translation of file permissions is getting messed up along the way.

Haven’t found a solution to this, but my current workaround is to:

(1) -clean -build -cook -skipstage
(2) icacls “Z:\W\Project\Mobile\project\Binaries*” /q /c /t /reset
(3) -cook -stage -package -signed

This produces a proper IPA with no errors. Might be able to refine this more to skip the second cook or stage altogether, but the stage after the inital cook is where the error occurs and running icacls to publish permissions to all child objects fixes it.

tkuzman, were you able to find a solution?

Not a solution, but my workaround is this:

// For clean builds, copy a blank file to the Remote Manifest path and fix its files permissions
def manifestPath = "${scmPath}\\project\\Intermediate\\Remote\\Project\\IOS\\Development"
dir(manifestPath)
{
    bat "IF NOT EXIST Manifest.xml COPY NUL Manifest.xml"
    bat "icacls Manifest.xml /q /c /t /reset"
}

// For IOS, permissions from the mac build node need to be fixed so commands have to be executed in parts
bat "${runUAT} BuildCookRun -project=\"${scmPath}\\project\\Project.uproject\" -${params.Platform} -clientconfig=${params.Configuration} -clean -build -cook -skipstage -unattended"

bat "icacls \"${scmPath}\\project\\Binaries\\*\" /q /c /t /reset"

bat "${runUAT} BuildCookRun -project=\"${scmPath}\\project\\Project.uproject\" -${params.Platform} -clientconfig=${params.Configuration} -cook -stage -package -signed -unattended"

Essentially, for clean builds, I need to create the file beforehand, set the permissions, and then when UAT replaces it from the remote mac build node, it preserves them and can access the file. Then breaking the build process into two phases, fixing the permissions on the downloaded binaries between the two, resolves the rest of the issue.

Honestly, I haven’t dived into this too much but I’m guessing the EC2 Administrator user isn’t recognized by my VPC’s AD properly and having issues setting the correct permissions on download. Legitimate users have no issues using the mac build node for their local compilations so that is my likely guess. What I have works now though, so when I have time I may poke at it more to find something cleaner.

After this bug held us up for days I finally found the solution. tkuzman’s solution didn’t work for us as after the build finished UE immediately went on to archive the build and was unable to read the files it had just created!

After a lot of digging I found the rsync used is an ancient cygwin version from 2003. This is part of the problem, but also the solution, because in those old versions you could set an environment variable that would override the permissions behaviour… so I was eventually able to simplify the build to this:

(We also set HOMEPATH because relying on the build machine to have up to date known_hosts files is fragile).

            homedrive = env.WORKSPACE.substring(0,2)
            homepath = env.WORKSPACE.substring(2)
        
            withEnv(["HOMEDRIVE=$homedrive", "HOMEPATH=$homepath", "CYGWIN=nontsec"])
            {                
    					bat "$UAT BuildCookRun -nocompileedtior -nop4 -project=\"${WORKSPACE}\\${PROJECT_NAME}.uproject\" -targetplatform=${params.PLATFORM} -cookflavor=${params.PLATFORM} -target=${PROJECT_NAME} -ue4exe=\"C:\\Epic\\${params.ENGINE_VERSION}\\Engine\\Binaries\\Win64\\UE4Editor-Cmd.exe\" -map=${mapName} -archive -archivedirectory=\"${env.WORKSPACE}\\Build_Files_${params.PLATFORM}\" -clientconfig=Shipping -compressed -archive -prereqs -distribution -nodebuginfo -targetplatform=IOS -utf8output ${CLEAN} -build -cook -stage -package -signed -unattended"
            }

The trick is the CYGWIN=nontsec environment variable.