Strategy for customizing Cocoapods - cocoapods

Note: I can see this question has been asked once before here: Right way to extend or customize cocoapods
but I am unsatisfied with the answer. Some more specifics would be great in the case where rather than simply adding new methods, etc., you wish to fundamentally alter the nature of the pod, and don't really have the time to submit a patch to the original pod owner (nor would they necessarily want to pull your app-specific changes to their generalized project).
Right now I am working on a project that makes significant use of Cocoapods, but currently the project's Pods directory is more or less frozen due to customizations of multiple pods to suit the needs of the app.
Since the customizations were done directly in the pods classes, the Pods project needs to be frozen from new installs/updates because it doesn't seem to be possible to add or update single pods without doing them all at the same time. Doing this naturally results in errors when the customizations get wiped out by the update.
I know that a feature to update individual pods was introduced in a recent version of Cocoapods, but that new version seems to introduce new issues where "Analyzing dependencies" will often error out with incorrect circular dependencies between a single pod and itself.
And as far as I know, there is no way to add a single pod without updating the others at the same time.
So then, what are people's strategies for customizing pods without getting into this kind of situation? Do you subclass in your main project while leaving the pods directory untouched?
At the end of the day, are pods really that much better than git submodules?
Thanks for advice as to how to make use of them while still customizing freely and not wind up in this kind of situation.
Right now my perspective is that pods which will be used without alteration can be imported to the Pods project as usual, but pods that are heavily customized should be added to the main project and separated from the pod add/update process completely.

You should never make changes to any Pod directly.
What you should do, if you really must change the behavior of the dependency (i.e., you can't solve the problem with any other alternative such as composition or even categories), you should create a fork and then make the changes there.
Then, on your Podfile you should add the link to your fork:
pod 'MyLib', :git => 'https://github.com/someuser/MyLib.git'
Also, none of your Pods should ever make reference to your app code. A dependency should be self-contained.
All of these problems you're having is not CocoaPods' (or any other tool) fault. They're happening because you (and your team) misused it.

Related

Inhibit warnings for subspec dependency

I'm developing a Pod that have a external dependency, which shows a lot of warnings in Xcode when using my Pod in an App.
What I want to do is remove all those warnings since it could quite annoying to see for those who use my Pod.
Is there a way to solve this? I'm trying several parameters in the subspec.xcconfig setting but I'm not able to find a solution.

somehow get notified when a pod has a new version

I'm using Pods in different iOS projects, now I would like to somehow get notified when a new version is released for one of the pods - no matter if via mail, rss feed or whatever. Does such a possibility exist?
A Podfile will generally semantically constrain the allowed versions of a pod (see semantic versioning):
pod 'Bolts', '~> 1.7'
This example would accept versions from 1.7 up to 2.0 excluded.
So the only way to know if there is a new version that fits your project is to run specifically for your repo:
pod outdated
Knowing that, you can script a Jenkins job to check it periodically.
Try https://www.versioneye.com/ . Not sure how well it works though.

Quick Go project build with Docker without checking in vendor libraries

Currently, we have all vendored libraries in src/vendor which makes docker-compose build quite fast. Although adding vendored libraries to source control has the disavantage of libraries not being updated and also heavily polluting the diff of pull requests.
Is there a way in between, maybe with caching?
Is there a way in between, maybe with caching?
Yes, several. But don't fight the system/preferred method.
Use $GOPATH/src/MyProject/vendor like you are already doing.
adding vendored libraries to source control has the disavantage of libraries not being updated...
That all depends on your team's management of your repo. If everyone ignores the vendor, ya it will get stale.
Personally I make it a "1st of the month" habit of going through and refreshing all dependencies, running our test suites, and if no errors update for QA integration testing on the dev server and keep an eye on the error logs after release. Tools like godep and gostatus greatly help keep your GOPATH in chrcn with latest, that you can update your vendor folder(s) with quickly.
Just make sure it is a dedicated commit, so it can be reverted in a hurry if an issue creeps up.
also heavily polluting the diff of pull requests
First of all, that's just a process task. I enforce rebasing on all pull requests and reject all merges in all repos. This keeps a very clean git history; but, more to the point, rebasing moves your local commits until after the vendor updates. Shouldn't ever get a conflict unless someone added the same package. Which at that point is easy, just take the latest one and be done.
Sound like there are process issues to work out than worrying about /vendor management.

Xcode Static libraries building in wrong folder

I've setup cocoapods for my project and I've been doing development for quite some time without any issues. Recently I added a new Configuration for it called "Beta", duplicating the "Release" configuration. At the same time, I added a Scheme that would build targets using this configuration.
This new scheme would build everything without issues, but linking would fail with the (quite known it seems) message:
ld: library not found for -lPods
I know that issues that makes this error message come up have been discussed widely around the web, with different causes and conditions:
library not found for -lPods
https://github.com/CocoaPods/CocoaPods/issues/155
None of these fixes seem to apply here. What I can see by looking into the workspace folder, is that Cocoapods build products are put in Build/Products/Release-iphonesimulator instead of in Build/Products/Beta-iphonesimulator, even though the app itself is built rightly so into the latter. Moving all the *.a files into Build/Products/Beta-iphonesimulator makes running in the simulator work properly, but the next build is still put in the wrong location.
Edit
After some further investigations, the environment variable $BUILT_PRODUCTS_DIR is set correctly in the build phase for the app itself, but not when building cocoapods products.
What causes this and how can I fix this?
Ruled out issues
pod install has been run, multiple times
I'm working in the workspace, not in the project
The cocoapods configuration file in the new configuration is properly set
Build locations in the preferences seem fine
For the record, the issue has been solved. So, as I said, I use cocoapods, but my current setup is that a single podfile, and workspace is used for 3 projects that share some common libraries. As explained in this issue, cocoapods will only consider one project out of all those that are specified in the podfile, and it turns the one project (out of three) that it was using, didn't have the beta configuration, so it didn't feel the need to prepare for it. So when it was time to build the project with the beta configuration, cocoapods would be built for the release configuration, and put in some folder specific to release, so the beta project wouldn't be able to find it.
Fixing was a matter of creating the beta configuration for all projects present in the workspace, forcing cocoapods to prepare accordingly. Then, Xcode would be able to wire up everything appropriately.

What is the most effective way to lock down external dependency "versions" in Golang?

By default, Go pulls imported dependencies by grabbing the latest version in master (github) or default (mercurial) if it cannot find the dependency on your GOPATH. And while this workflow is quite simple to grasp, it has become somewhat difficult to tightly control. Because all software change incurs some risk, I'd like to reduce the risk of this potential change in a manageable and repeatable way and avoid inadvertently picking up changes of a dependency, especially when running clean builds via CI server or preparing to deploy.
What is the most effective way I can pin (i.e. lock down or capture) a package dependency so I don't find myself unable to reproduce an old package, or even worse, unexpectedly broken when I'm about to release?
---- Update ----
Additional info on the Current State of Go Packaging. While I ended up (as of 7.20.13) capturing dependencies in a 3rd party folder and managing updates (ala Camlistore), I'm still looking for a better way...
Here is a great list of options.
Also, be sure to see the go 1.5 vendor/ experiment to learn about how go might deal with the problem in future versions.
You might find the way Camlistore does it interesting.
See the third party directory and in particular the update.pl and rewrite-imports.sh script. These scripts update the external repositories, change imports if necessary and make sure that a static version of external repositories is checked in with the rest of the camlistore code.
This means that camlistore has a completely repeatable build as it is self contained, but the third party components can be updated under the control of the camlistore developers.
There is a project to help you in managing your dependencies. Check gopack
godep
I started using godep early last year (2014) and have been very happy with it (it met the concerns I mentioned in my original question). I am no longer using custom scripts to manage the vendoring of dependencies as godep just takes care of it. It has been excellent for ensuring that no drift is introduced regardless of timing or a machine's package state. It works with the existing mechanism of go get and introduces the ability to pin (godep save) and restore (godep restore) based on Godeps/godeps.json.
Check it out:
https://github.com/tools/godep
There is no built in tooling for this in go. However you can fork the dependencies yourself either on local disk or in a cloud service and only merge in upstream changes once you've vetted them.
The 3rd party repositories are completely under your control. 'go get' clones tip, you're right, but you're free to checkout any revision of the cloned-by-go-get or cloned-by-you repository. As long as you don't do 'go get -u', nothing touches your 3rd party repositories already sitting at your hard disk.
Effectively, your external, locally cloned, dependencies are always locked down by default.

Resources