The new embrace-apple-sdk is open source! This is a new observability framework created with extensibility in mind. It uses OpenTelemetry as its data model and persists data to disk using SQLite via GRDB.
I want to share a key decision that the iOS team had to make – whether to open source versus build in public. Since these two options have very different development processes, it was important that we choose what ultimately works best for our team.
In this post, I’ll cover our thought process in making this decision, as well as how we created our CI/CD process for delivering new SDK releases into our public repo. Feel free to copy our approach if you find it helpful, as there’s nothing specific to iOS or mobile development in our workflow.
Let’s start off by explaining what I mean when I say there’s a difference between open source versus building in public.
Open source vs. building in public
Open source is hopefully a straightforward term. We distribute our source code publicly, to allow for transparency in how the system works and to get feedback on the implementation so we can make improvements that would otherwise be overlooked. The nature of it being public also means that code quality must take high priority during development to ensure that it is understandable to people unfamiliar with the project.
Building in public is a step above open source in my eyes. It means not only is the source public, but all issues, pull requests, and any attached conversation is also public via a forum, public boards, or pull requests. This is an excellent practice as it allows feedback and ideas to be shared before any code is written.
A team decision
So what did we decide works for us? Well actually, and unsurprisingly, we came out with a split decision. The team behind the embrace-android-sdk decided they would build in public. All pull requests go directly to the public repo, and any discussion that comes up happens openly. On the other hand, the team behind the embrace-apple-sdk chose a different approach. We decided that only when we merge into main should the public repo be updated. This means any pull request you see in this repo has come from an external contributor (who we appreciate greatly).
I should step back and mention that last year our company moved all our internal issue tracking into Notion, which allows everyone to be on the same page when it comes to project management, documentation, and content creation. This shared space allows us to coordinate between the technical and non-technical aspects of software. This company-wide decision is why our “Issues” pages look slimmer than you may think for an active software project. We expect (and hope) our number of GitHub Issues will increase as developers try out the project, ask questions, and share feedback with us. Please create a GitHub Issue and open the discussion!
The deciding factor
You may be wondering why our Android/iOS teams made different decisions when it came to how to manage the open source projects. I can say the biggest factor that went into the iOS team’s decision to keep our development and pull requests internal comes down to one of the core cultural tenets at Embrace, which is: Deliver brutal honesty kindly. Our team felt at the time that building in public may prevent us from providing honest feedback when necessary. We also wanted to make sure that if discussion turns into forward-looking plans, we wouldn’t be exposing anything that we may decide not to implement.
The ability to have these discussions internally allows us to openly discuss any proposed changes. It also provides a buffer to prevent any unwanted information (roadmap or client-related) from being exposed. We may decide to revisit this approach in the future, but for now, this process is what works best for our team.
How we push updates
We have a private repo where we do all our normal development. Developers use this as their origin
git remote. The public repo embrace-apple-sdk
is then a separate remote that can be thought of as a public mirror. To help automate the process of pushing to our public remote we have a script bin/publish that we use in order to sync to the public remote. This script will:
- Use the
PUBLIC_REMOTE_URL
envvar to temporarily create a remote namedpublic
. If apublic
remote already exists, it will use that one.
# Add public repo as remote if it is not already added
if ! git remote | grep -q "$PUBLIC_REMOTE_NAME"; then
git remote add "$PUBLIC_REMOTE_NAME" "$PUBLIC_REMOTE_URL"
# Remove the remote when the script exits
trap 'git remote remove "$PUBLIC_REMOTE_NAME"' EXIT
# else check if public remote has the same repo URL
elif ! git remote get-url "$PUBLIC_REMOTE_NAME" | grep -q "$PUBLIC_REMOTE_URL"; then
echo 'Error: $PUBLIC_REMOTE_NAME remote has a different URL.' >&2
echo "Run 'git remote set-url $PUBLIC_REMOTE_NAME $PUBLIC_REMOTE_URL' to update" >&2
exit
fi
- Push the current HEAD to the
public
remote using the same name.
# Push current branch to public remote
git push "$PUBLIC_REMOTE_NAME" "$(git rev-parse --abbrev-ref HEAD)"
- Optionally push all tags if the
--tags
option is included.
# Push tags to public remote if --tags flag is set
if [ "$PUBLISH_TAGS" = true ]; then
git push "$PUBLIC_REMOTE_NAME" --tags
fi
- Remove the
public
remote if this script had created it (seetrap
in step 1).
That’s it! In a couple easy steps we’ve got the ability to share our development with the world!
Now let’s automate it
Now that we have that working, let’s automate it so our main branch is updated seamlessly. To do this, we use GitHub Actions and have a custom “Publish” workflow. You can take a look here.
We run tests first by calling our existing test workflow, then we simply run the publish job which is:
name: Publish
on:
workflow_dispatch: {}
push:
branches:
- main
jobs:
# run test job...
publish:
runs-on: ubuntu-latest
needs: run-tests-workflow
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.THE_GITHUB_TOKEN }}
fetch-depth: 0
timeout-minutes: 2
- name: Run publish script
env:
PUBLIC_REMOTE_URL: ${{ vars.PUBLIC_REMOTE_URL }}
GITHUB_TOKEN: ${{ secrets.THE_GITHUB_TOKEN }}
run: |
bin/publish
There’s nothing special here, just a call to our custom bin/publish
script with an environment variable we’ve configured in our internal repo to set the PUBLIC_REMOTE_URL
to https://github.com/embrace-io/embrace-apple-sdk.git
Conclusion
For teams that are thinking about going open source, but may not yet want to take the leap and build in public, a pattern like this is something I’d recommend. Keep your development internal and let your team work as it normally does. Automate your code distribution with a script like this and make your “release” day checklist as simple as possible.
It’s important to keep in mind that teams will work differently, and teams want to have the autonomy to control what they create. So do what works best for you and make your own decisions when it comes to open source versus build in public. There is no wrong answer as long as your team is comfortable and your process is as smooth as possible.
Bonus
I wanted to share some extra material in case you want to try our CI/CD approach on your team:
- Please steal this! I may work on our iOS team but there is nothing specific to iOS or mobile development here. This is just generic
git
sprinkled with the most basic GitHub Action. If you have feedback or recommendations, open an issue! - You may wonder about our release process. We use semantic versioning as best as possible, and mark these versions with git tags. When we want to push a new tag to be public, we run
bin/publish --tags
from ourmain
branch.
Learn more about leveraging Embrace’s open-source SDKs for mobile observability.
Get started free