99 Contributions to Open Source graphql-go
99 Contributions to Open Source graphql-go: Experiences, Best Practices, and Lessons Learned
Open source is more than just a buzzword; in the world of software engineering, it is a space for learning, growing, and genuine collaboration. One of the most valuable experiences in my open source journey was contributing as many as 99 pull requests to the graphql-go
project, a leading GraphQL library in the Golang ecosystem.
This article summarizes my journey: the motivation, the types of contributions, the challenges, code simulations, and the best practices I discovered along the way. If you want to become a capable contributor, or if your team wants to build a healthy open source culture, read all the way to the end!
Why graphql-go?
Before getting started, here are a few reasons why I chose graphql-go:
- Widely used – Many production projects in Indonesia and around the world use Go for the backend, and GraphQL has become the API of choice today.
- A growing ecosystem –
graphql-gois very open to contributors, with an active issue tracker and plenty of feature needs. - Real challenges – Implementing GraphQL in Go requires an understanding of the type system, reflection, performance, and security.
99 Contributions… What Were They Exactly?
Not every contribution has to be a flashy “wow” feature. Here is a breakdown of my 99 contributions to graphql-go:
| Contribution Type | PR Count | Example |
|---|---|---|
| Bug fixes | 23 | Fix panic on resolving an interface |
| Feature additions | 17 | Enum coercion, custom error handler |
| Refactoring | 21 | Split the resolvers.go file |
| Documentation | 14 | Update README, code comments |
| Writing tests | 11 | Add missing interface test |
| PR reviews | 13 | Comments & suggestions for other PRs |
Interesting, isn’t it? Only 17 out of 99 PRs were new features. The rest ensured stability, readability, and code quality.
The Contribution Process: A Real-World Simulation
Let’s simulate one of the simpler contributions that turned out to add significant value: adding Enum field validation.
The Original Problem
In the old implementation, Enums did not perform case-sensitiveness checks optimally. A user could send the enum STATUS_active, even though it should only accept STATUS_ACTIVE.
Flow Diagram: Enum Validation
flowchart TD
A[Query Masuk] --> B{Field Type Enum?}
B -- Tidak --> C[Lewat Normal]
B -- Ya --> D{Value Valid?}
D -- Tidak --> E[Kembalikan Error]
D -- Ya --> F[Lanjutkan Resolving]
The Code Before
1// Before the patch: Enum without proper case checking
2if enumType, ok := field.Type.(*graphql.Enum); ok {
3 value := params.Args["status"]
4 // Accepted without a case-sensitive check
5 if _, ok := enumType.ValuesMap[strings.ToUpper(value.(string))]; !ok {
6 return nil, errors.New("Invalid enum value")
7 }
8}The Code After the Patch
1// After the fix: strict case-sensitive check
2if enumType, ok := field.Type.(*graphql.Enum); ok {
3 value := params.Args["status"]
4 // Accept only on an exact match
5 if _, ok := enumType.ValuesMap[value.(string)]; !ok {
6 return nil, errors.New("Nilai enum tidak valid")
7 }
8}A small fix? Yes. But this PR reduced silent errors and improved the downstream developer experience.
Key Lessons from Every Stage
1. The Importance of Documentation
Before writing code, I often fixed docstrings and the README first. Good documentation speeds up the onboarding of new contributors.
2. Comprehensive Testing
Writing tests is not just about covering the code, but also about providing a safety net for those who come after you.
Here is a basic table-driven Enum test example in Go:
1func TestEnumStrictCase(t *testing.T) {
2 enumType := graphql.NewEnum(graphql.EnumConfig{
3 Name: "Status",
4 Values: graphql.EnumValueConfigMap{
5 "ACTIVE": &graphql.EnumValueConfig{Value: 1},
6 "INACTIVE": &graphql.EnumValueConfig{Value: 2},
7 },
8 })
9 cases := []struct{
10 input string
11 valid bool
12 }{
13 {"ACTIVE", true},
14 {"active", false},
15 {"INACTIVE", true},
16 {"INACTIVITY", false},
17 }
18 for _, c := range cases {
19 _, ok := enumType.ValuesMap[c.input]
20 if ok != c.valid {
21 t.Errorf("for input %v, expected %v, got %v", c.input, c.valid, ok)
22 }
23 }
24}3. Effective Communication
For every PR, I always filled in the description: “Motivation”, “Solution”, “Demo”, “Compatibility impact”. This speeds up the review and saves the maintainers’ time.
4. Incremental Refactoring
Large refactors make a codebase easier to understand.
I started by splitting a monolithic file into per-module files:
1$ git mv schema.go schema/types.go
2$ git mv executor.go executor/resolve.goAs a result, new contributors can easily identify the entry point relevant to each concern.
5. Reviewing and Supporting Other Contributors
Reviewing other contributors’ PRs is not just a matter of courtesy; it strengthens a shared sense of ownership.
Best Practices Based on the Experience of 99 PRs
- Open small, focused PRs. One PR, one major change. Easier to review.
- Test before push. Use
go test ./...and make sure coverage goes up. - Write clear commit messages.
fix(enum): strict case checkingis far better thanupdate enum. - Be active in discussions. Open issues, leave comments, and start conversations about the implementation.
- Review the documentation, not just the code. A code change ≠ done without a docs update.
- Embrace feedback. Suggestions from maintainers = a learning opportunity that is sometimes more important than the coding itself.
The Impact of This Experience on My Career
After 99 contributions, I:
- Became more confident reading a large codebase
- Understood the process of upstream bugfixing and open source releases
- Built networking with engineers abroad through reviews and issue discussions
- Received remote job offers thanks to my OSS activity
Even small contributions, when made consistently, build team trust and increase your visibility in the global community.
Building a Contribution Roadmap: A Simulation
What strategy makes your contributions optimal? Here is a 5-step roadmap based on experience:
flowchart TD
A[Mulai Dari Isu Mudah] --> B[Perbaiki Dokumentasi & Tes]
B --> C[Lanjut Refactoring Minor]
C --> D[Implementasi Fitur Kecil]
D --> E[Review PR & Aktif Diskusi]
Don’t jump straight into a “big PR”. The deeper your contributions go, the more trust you build with the maintainers and the community.
Conclusion
Reaching 99 contributions to the open source graphql-go taught me that impact comes not just from lines of code, but from collaboration, documentation, and shared perseverance.
No matter how many PRs you have, what matters is that each contribution brings higher quality. And make no mistake: small PRs move OSS forward faster than big, infrequent commits.
Ready to write your contribution #1?
Open up the graphql-go repo today and find a simple issue – the open source world is always open to those who want to learn!
Happy contributing, and see you on the next pull request! 🚀