Skip to content

Conversation

spencertransier
Copy link
Contributor

@spencertransier spencertransier commented Mar 1, 2023

Summary

This PR adds a caching action for Swift Package Manager to the CI toolkit. Some notes:

  • It works for both workspace-based repos like WCiOS, DOiOS/Mac, etc. along with non-Xcode repos like hostmgr or Swift packages if they have SPM dependencies. The action automatically detects what kind of repo it is based on where the Package.resolved file is located.
  • I used the existing install_swiftpm_dependencies action because I didn't see it being used elsewhere. If that's incorrect (@jkmassel & @AliSoftware looks like you both worked on that action in the past), please let me know and I can move SPM caching into a separate action.
  • This is my first time diving into bash scripting. If there are conventions I'm not following or better ways of doing something, please let me know!

How to Test

You can see this CI build of Day One iOS/Mac that's using the latest caching code:

Example Builds:

There is now a "Restoring SPM Cache" step:

Screenshot 2023-03-01 at 3 39 13 PM

To try regenerating the cache, you can delete any of the day-one-spm-cache... files from the a8c-ci-cache and re-run the build to verify that the cache rebuilds.

@spencertransier
Copy link
Contributor Author

spencertransier commented Mar 1, 2023

Question about the Shellcheck error I'm getting:

In bin/save_cache line 58:
[2023-03-01T23:35:12Z] tar $TAR_OPTIONS -czf "$CACHE_KEY" -C "$CACHE_FILE" .
[2023-03-01T23:35:12Z] ^----------^ SC2086 (info): Double quote to prevent globbing and word splitting.

It's referring to $TAR_OPTIONS not being surrounded in quotes. The issue is that if I add the quotes, the tar options that I'm passing to save_cache from install_swiftpm_dependencies don't actually get used by tar when archiving the cache. In this case, I'm passing folders that should be excluded when creating the cache archive.

Without the quotes around $TAR_OPTIONS in save_cache, the folders are excluded from the archive as expected. With the quotes, the --exclude options are ignored and the folders are not excluded from the archive.

I'm just not sure why adding the quotes is doing that. Any suggestions about what could be changed to allow for the quotes to be added? I know this is just an info issue with Shellcheck. I assume we have Shellcheck fail for info issues for a reason, so I didn't want to ignore this one even though it's not even a warning.

@spencertransier spencertransier marked this pull request as ready for review March 2, 2023 00:08
@spencertransier spencertransier requested review from a team and jkmassel March 2, 2023 00:08
@AliSoftware
Copy link
Contributor

AliSoftware commented Mar 2, 2023

@spencertransier Adding the quotes around "$TAR_OPTIONS" means that if that variable contains eg --exclude Foo then it will consider "--exclude foo" as a single argument (one which contains spaces) as opposed to two.

On the other hand, not quoting the $TAR_OPTIONS means that if it contains --exclude foo it'll see it as two individual arguments like you probably want… but that also means that if the folder you want to exclude contains a space, eg --exclude my project it will see it as three distinct arguments (--exclude, my and project)

The best solution for your case is probably to use the bash array syntax to build your list or tar options (whose syntax I always forget but a quick search on the net should help)

# `artifacts` should be excluded because it causes issues when downloading
# certain packages to have the artifacts already present after extracting
# cache
TAR_OPTIONS="--exclude=./checkouts --exclude=./artifacts"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than fighting with bash syntax regarding using quote or not, I'm wondering if it'd be simpler to just delete these unwanted files from the SPM_CACHE_LOCATION?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or, copy the "SPM_CACHE_LOCATION", delete the unwanted files from the new copy, call save_cache on the new copy, and delete the new copy afterwards.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AliSoftware Thank you for the explanation! The array solution makes a lot of sense after the behavior I saw while debugging this.

@crazytonyli Good idea! I think I'm going to go with deleting those directories before saving the cache. It removes the complexity of passing the tar options along with simplifying the changes to save_cache.


CUSTOM_PACKAGE_RESOLVED_PATH=${1-}
BUILD_TYPE=${2-}
SPM_CACHE_LOCATION="$HOME/spm"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There exists a $HOME/.swiftpm/cache folder on my Mac that was probably created by SPM itself at some point.

I wonder if we shouldn't use that folder (for conventions) as opposed to ~/spm here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, good point! Jeremy and I had discussed using the cache that's within DerivedData, but I wasn't able to make that work because there's not a consistent path name within DerivedData. But it does work great with making the cache location in the script point to $HOME/Library/Caches/org.swift.swiftpm. And that has the added benefit of client repos not needing to specify a specific SPM cache folder in the Fastfile. Package resolution will pull from that org.swift.swiftpm folder automatically when resolving the packages.

Added in 44785e4

bin/save_cache Outdated
echo " Compressing"
tar -czf "$CACHE_KEY" "$CACHE_FILE"
TAR_CONFIG=${4-}
if [[ "$TAR_CONFIG" == '--use_alternate_tar_config' ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit but I'm not a fan of the name of this custom flag… what about --use_relative_path_in_tar or something like that instead?


Also, I'm wondering if it wouldn't make sense to adopt that -C behavior… in all circumstances after all (seems a nicer solution than including /User/builder in the cache path and risking the un-tar-ing to fail if used on a different builder which might not have a /User/builder folder (all our Mac VMs currently do, but we shouldn't need to make that assumption, and also nothing says the cache would be restored on a Mac VM vs an Android AMI or Docker container or whatnot, so…).

That one might be a broader investigation to verify that changing that behavior that save_cache was using so far (and you kept in the else) to instead use -C "$CACHE_FILE" . in all cases would not break existing setups depending on how they use restore_cache on their end; so could be saved for a subsequent PR if you're not sure about that. But would be a nice simplification if we can confirm it and go in that direction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I like --use_relative_path_in_tar better, too. Changed in b919255

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if it wouldn't make sense to adopt that -C behavior in all circumstances.

I agree that would be nice to use the same behavior for all cases if possible. Because I saw different behavior between the existing tar configuration versus the one I added in this PR, I had assumed the projects that use save_cache would need to be updated and cause a breaking change. I haven't tested that out yet, but I think it'd be outside the scope for this project. I'll create a separate issue for it.


# If this is the first time we've seen this particular cache key, save it for the future
echo " Saving SPM Cache"
save_cache "$SPM_CACHE_LOCATION" "$CACHE_KEY" false --use_relative_path_in_tar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker. This sequence of argument feels prone to errors, it's probably worth looking into parsing the arguments and options, using getopts for example. Statement as below would look much nicer 😸

save_cache --cache-key "$CACHE_KEY" --overwrite --use_relative_path_in_tar "$SPM_CACHE_LOCATION"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion! I am going to land this PR and work on improving this in my next iteration of the SPM caching and save_cache improvements.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #54

cd -

# This will let Xcode use the system SSH config for downloading packages
sudo defaults write com.apple.dt.Xcode IDEPackageSupportUseBuiltinSCM YES
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not part of this PR. Is this preference same as xcodebuild -scmProvider system?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crazytonyli I think so but I'm not sure. I will look into this and see about adding in the next update of the SPM caching action.

@spencertransier spencertransier enabled auto-merge (squash) March 9, 2023 22:45
@spencertransier spencertransier merged commit e257e89 into trunk Mar 9, 2023
@spencertransier spencertransier deleted the add/spm-caching-actions branch March 9, 2023 22:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants