{"id":1066,"date":"2024-07-23T14:29:06","date_gmt":"2024-07-23T14:29:06","guid":{"rendered":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2024\/07\/23\/how-we-organize-and-get-things-done-with-serviceowners\/"},"modified":"2024-07-23T14:29:06","modified_gmt":"2024-07-23T14:29:06","slug":"how-we-organize-and-get-things-done-with-serviceowners","status":"publish","type":"post","link":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/2024\/07\/23\/how-we-organize-and-get-things-done-with-serviceowners\/","title":{"rendered":"How we organize and get things done with SERVICEOWNERS"},"content":{"rendered":"<p>GitHub\u2019s primary codebase is <a href=\"https:\/\/github.blog\/2023-04-06-building-github-with-ruby-and-rails\/\">a large Ruby on Rails monolith<\/a> with over 4.2 million lines of code across roughly 30,000 files. As the platform has grown over the years, we have come to realize that we need a new way to organize and think about the systems we run. Our traditional approach to organizing Hubbers and code has been through <a href=\"https:\/\/docs.github.com\/repositories\/managing-your-repositorys-settings-and-features\/customizing-your-repository\/about-code-owners\">CODEOWNERS<\/a> in combination with GitHub teams, organizations, issues, and repositories. However, as GitHub\u2019s user base continues to grow, we have discovered we need a new layer of abstraction. This is where SERVICEOWNERS comes in.<\/p>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Service-oriented_architecture\">Service-oriented architecture<\/a> is not new, but we do not talk often about how large engineering teams organize around services\u2013especially in a hybrid monolith\/services architecture. GitHub engineering determined that we were missing a layer in between CODEOWNERS, how we group humans, and work to be done. Injecting a \u201cservice\u201d layer between groups of functionality and the people maintaining them opens up a number of interesting possibilities.<\/p>\n<p class=\"purple-text text-gradient-purple-coral mt-6 mb-6\">One side-effect of adopting SERVICEOWNERS was realizing that the \u201cownership\u201d model does not quite express how we work. Given our place in the open source ecosystem and what we value as a company, we thought the \u201cmaintainer\u201d model more accurately describes the relationships between services and teams. So, no team \u201cowns\u201d anything, but instead they \u201cmaintain\u201d various services.<\/p>\n<h2>Consistent, company-wide grouping<a href=\"https:\/\/github.blog\/engineering\/#consistent-company-wide-grouping\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h2>\n<p>Achieving consistency in how we map running code\u2013both within and without our monolith\u2013to humans has had a number of positive outcomes. It promotes a shared lexicon, and, therefore, a shared understanding. The durability of services reduces the disruption of team reorganization. As priorities shift, services stay the same and require only minimal updates to yaml metadata to be accurate. Consistency in our service definitions also allows us to centralize information about the services we run into a service catalog. Our service catalog is the one-stop shop for up-to-date information on the services that power GitHub. Within the catalog, Hubbers of all stripes can find information on, for example, how a service is performing vis-a-vis an <a href=\"https:\/\/en.wikipedia.org\/wiki\/Service-level_objective\">SLO<\/a>. Each service in the service catalog also has a number of scorecards as part of our fundamentals program.<\/p>\n<p>With clearly defined services collected in a service catalog, we can easily visualize the relationships between services. We can identify dependencies and map how information flows through the platform. All this information improves the onboarding experience for new engineers, too, as the relationships between services define the platform architecture\u2014without having to rely on out-of-date docs or hand-waving to explain our architecture.<\/p>\n<p>The service catalog also has the huge benefit of centralizing information about which teams maintain which services, how to reach an on-call engineer, and what expectations the service has set in terms of support SLAs. Clean lines of communication to maintainers of running services has been a huge help in reducing our incident remediation time. Incident commanders know how to contact on-call engineers because they can find it in the service catalog. All of this is only possible thanks to SERVICEOWNERS.<\/p>\n<h2>How it works<a href=\"https:\/\/github.blog\/engineering\/#how-it-works\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h2>\n\n<h3>The SERVICEOWNERS file<a href=\"https:\/\/github.blog\/engineering\/#the-serviceowners-file\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h3>\n<p>A SERVICEOWNERS file lives next to the CODEOWNERS file within our monolith. Like a traditional CODEOWNERS file, SERVICEOWNERS consists of a series of glob patterns (for example, app\/api\/integration*), directory names (for example, config\/access_control\/) and filenames (for example, app\/api\/grants.rb) followed by a service name (for example :apps maps to the team github\/apps). Our CI enforces rules like:<\/p>\n<p>There can be no duplicate patterns\/directories\/files in SERVICEOWNERS.<br \/>\nAll new files added to the github\/github repository must have a service owner.<br \/>\nAll patterns\/directories\/files must match at least one existing file.<br \/>\nFiles matched by multiple glob patterns must be disambiguated by a file or directory definition.<\/p>\n<h3>The service-mappings.yaml file<a href=\"https:\/\/github.blog\/engineering\/#the-service-mappings-yaml-file\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h3>\n<p>A service-mappings file defines how services referenced in the SERVICEOWNERS file relate to services in the service catalog and GitHub teams. This configuration can define a service\u2019s product manager, engineering manager, repository, and chat information. Service mappings can also define information about a service\u2019s various classifications, such as its \u201ctier\u201d rating, with zero being critical to the GitHub platform and three being experimental\/non-critical.<\/p>\n<h3>The serviceowners gem<a href=\"https:\/\/github.blog\/engineering\/#the-serviceowners-gem\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h3>\n<p>We have developed a Ruby gem we integrate with our Rails app that combines data from the SERVICEOWNERS and service-mappings files to produce several types of output. The serviceowners gem generates our CODEOWNERS file. So, instead of manually updating CODEOWNERS, changing which team or teams maintain a service is a one-line YAML change. The serviceowners gem also has an executable which allows engineers to query information about the maintainer of a file or which files a service maintains.<\/p>\n<p>Because it\u2019s GitHub, there\u2019s of course also <a href=\"https:\/\/github.blog\/2020-10-22-devops-best-practices-qa-automated-deployments-at-github\/\">a chat-op<\/a> for that:<\/p>\n<p>\n  <strong>me<\/strong>: hubot serviceowners for test\/jobs\/do_the_thing_with_the_stuff_test.rb<\/p>\n<p>  <strong>hubot<\/strong>: The file test\/jobs\/do_the_thing_with_the_stuff_test.rb is part of the github\/some_service service and is maintained by the cool-fun-team team who can be reached in #hijinx.\n<\/p>\n<h3>The ownership.yaml file<a href=\"https:\/\/github.blog\/engineering\/#the-ownership-yaml-file\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h3>\n<p>The above examples mostly focus on breaking up the monolith into services, but our service catalog can slurp up service information from any repository within the GitHub org that has an ownership.yaml file. Like the service-mappings file, ownership expresses version controlled values for various service metadata. This allows us to have the boundaries of a service span across multiple repositories; for example, the GitHub Desktop app can have a component service within the monolith while also having its own standalone artifact from a different repository. Another benefit of the ownership file is that it allows us to focus code changes to the monolith codebase primarily around functionality and not maintainership.<\/p>\n<h2>Conclusion<a href=\"https:\/\/github.blog\/engineering\/#conclusion\" class=\"heading-link pl-2 text-italic text-bold\"><\/a><\/h2>\n<p>The combination of CODEOWNERS and SERVICEOWNERS has provided serious value for us at GitHub. The tooling we continue to build atop these primitives will serve to make maintaining services clearer and easier. That\u2019s good news for the future of GitHub. It also pairs quite nicely with our open source identity and access management project, <a href=\"https:\/\/github.blog\/2022-06-09-introducing-entitlements-githubs-open-source-identity-and-access-management-solution\/\">entitlements<\/a>, too. If SERVICEOWNERS sounds like something your organization, open source or corporate alike, would benefit from, let us know on X at @<a href=\"https:\/\/twitter.com\/github\">github<\/a>.<\/p>\n<p>The post <a href=\"https:\/\/github.blog\/engineering\/architecture-optimization\/how-we-organize-and-get-things-done-with-serviceowners\/\">How we organize and get things done with SERVICEOWNERS<\/a> appeared first on <a href=\"https:\/\/github.blog\/\">The GitHub Blog<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>GitHub\u2019s primary codebase is a large Ruby on Rails monolith with over 4.2 million lines of code across roughly 30,000 [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[8],"tags":[],"class_list":["post-1066","post","type-post","status-publish","format-standard","hentry","category-github-engineering"],"_links":{"self":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1066","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/comments?post=1066"}],"version-history":[{"count":0,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/posts\/1066\/revisions"}],"wp:attachment":[{"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/media?parent=1066"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/categories?post=1066"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rssfeedtelegrambot.bnaya.co.il\/index.php\/wp-json\/wp\/v2\/tags?post=1066"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}