123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- <!doctype html><!-- This is a valid HTML5 document. -->
- <!-- Screen readers, SEO, extensions and so on. -->
- <html lang="fr">
- <!-- Has to be within the first 1024 bytes, hence before the `title` element
- See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
- <meta charset="utf-8">
- <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
- <!-- The viewport meta is quite crowded and we are responsible for that.
- See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <!-- Required to make a valid HTML5 document. -->
- <title>Sustaining Maintaining (archive) — David Larlet</title>
- <meta name="description" content="Publication mise en cache pour en conserver une trace.">
- <!-- That good ol' feed, subscribe :). -->
- <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
- <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
- <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
- <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
- <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
- <link rel="manifest" href="/static/david/icons2/site.webmanifest">
- <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
- <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
- <meta name="msapplication-TileColor" content="#f7f7f7">
- <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
- <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
- <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
- <!-- Documented, feel free to shoot an email. -->
- <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
- <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
- <script>
- function toggleTheme(themeName) {
- document.documentElement.classList.toggle(
- 'forced-dark',
- themeName === 'dark'
- )
- document.documentElement.classList.toggle(
- 'forced-light',
- themeName === 'light'
- )
- }
- const selectedTheme = localStorage.getItem('theme')
- if (selectedTheme !== 'undefined') {
- toggleTheme(selectedTheme)
- }
- </script>
-
- <meta name="robots" content="noindex, nofollow">
- <meta content="origin-when-cross-origin" name="referrer">
- <!-- Canonical URL for SEO purposes -->
- <link rel="canonical" href="https://daverupert.com/2021/12/sustaining-maintaining/">
-
- <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
-
-
- <article>
- <header>
- <h1>Sustaining Maintaining</h1>
- </header>
- <nav>
- <p class="center">
- <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
- </svg> Accueil</a> •
- <a href="https://daverupert.com/2021/12/sustaining-maintaining/" title="Lien vers le contenu original">Source originale</a>
- </p>
- </nav>
- <hr>
- <p>You see it all the time; a repo with a thousand issues, a hundred open PRs, a thousand forks. <code>v2.0</code> is on the way but there’s no clear roadmap or communication. Those of us who have worked on open source can spot it, burnout is afoot. The project got bigger than what the person or organization could realistically maintain. The maintainers are too busy or too burnt out to get the project back on track.</p>
- <p>My open source burnout saga is pretty standard. My coworkers and I made a jQuery plugin that solved a hole in the web platform. It got pretty popular, and we made another one, and another one. Then the issues started pouring in; the surprise refactors, the undiscussed feature drops, the commit stat beefers, the good ideas I don’t have time for, the bad ideas I don’t know how to say “no” to, and the endless “this doesn’t work and you’re a bad human” support requests.</p>
- <p>The critical issue for me was that open source was counter-cyclical to my life. I’d open source in slow times, but couldn’t manage client work and open source work in busy times. Out of principle we don’t work on weekends at Paravel… but people on GitHub sure do! Every Monday morning my inbox would be full of crushing guilt and neglected responsibility as issues piled up on my projects.</p>
- <p>For every issue closed, three new issues showed up. I love open source, but it felt endless and unmanageable. As burnout encroached, I went into self-preservation mode. I did a bit here and there, but sought refuge for my mental health in video games and comic books instead of working nights and weekends. Years went by and having children deleted any concept of spare time.</p>
- <p>It would be great if I had more time! But time requires money. Sentry and GitHub hosted a panel this week called “<a href="https://www.youtube.com/watch?v=dodos1n1-As">The Future of Open Source: Is It Sustainable?</a>” which was a candid discussion about funding. There’s different shapes funding can take, but most open source funding happens through either a dedicated employer, support contracts, a crowdfunding tip jar, or a foundation; the unifying factor seems to be maintainers get paid. Money helps make open source sustainable.</p>
- <p>But financials are one part of the sustainable open source equation. There’s an emotional cost to having a publicly available project that hundreds or thousands of people and companies depend on as well. One of the best talks I’ve heard on open source maintenance and one I reference often is Jacob Thornton’s 2012 dotJS talk “<a href="https://www.youtube.com/watch?v=UIDb6VBO9os">What Is Open Source & Why Do I Feel So Guilty?</a>”</p>
-
- <p>From the old Xerox PARC days to the open sourcing of Netscape in 1998 (which was the first use of the term “open source”) to the modern day <code>npm install whatever-i-want</code>; open source has come a long way. In ye olde times, we downloaded shareware from Sourceforge which was an effective way to install malware on your computer. GitHub’s launch in 2008 fundamentally changed how we build, share, and distribute software. It has even turned a proprietary titan like Microsoft into an open source advocate. <a href="https://onezero.medium.com/the-internet-relies-on-people-working-for-free-a79104a68bcc">The internet relies on people working for free</a>.</p>
- <p>Towards the end of the talk, Thornton gets to the heart of the issue:</p>
- <blockquote>
- <p>With the acceleration of GitHub making everything more efficient, making everything easier and easier, the time to burnout is accelerating at a break neck pace.</p>
- </blockquote>
- <p>“Burnout”. There’s the word.</p>
- <p>I sometimes wonder why a company like GitHub doesn’t offer educational, financial, or organizational support to maintainers. <a href="https://lab.github.com/">There’s plenty of write-ups on GitHub</a> about <em>how to start</em> a new open source project, or <em>how to add tooling</em>, but almost no information or best practices on <em>how to maintain</em> a project over years. I think there’s a big education gap and opportunity here. GitHub has an obvious incentive to increase <code>num_developers</code> and <code>num_repos</code>, but I think it’s worthwhile to ease the burden of existing developers and increase the quality and security of existing repos. Open source maintenance needs a manual.</p>
- <p>If I were to spitball some chapter titles or sections for a manual, it’d look like this:</p>
- <ul>
- <li>Differentiating between support requests and Issues</li>
- <li>Issue management (issue templates, labels, sticky issues, closing strategies)</li>
- <li>How to handle volume without losing your soul</li>
- <li>Landing pull requests from strangers (security concerns, etc)</li>
- <li>Setting up testing and continuous integration</li>
- <li>How to get Sponsors</li>
- <li>How and why to use Discussions</li>
- <li>How and why to use Projects and Milestones</li>
- <li>How to write good documentation</li>
- <li>Setting boundaries and office hours</li>
- <li>Effective and clear communication</li>
- <li>Choosing an open source business model</li>
- </ul>
- <p>Or what about offering in-person support? Developer Advocates could offer this list of services to project maintainers in exchange for livestream or video content. I’d love to see more content where existing projects get help on tooling or process instead of always starting from a blank repo. Call it “Pimp My Repo”, get Xzibit to host, sell it to MTV. I’d watch it. I’d also watch interviews with successful maintainers to learn about their maintenance routines. It’d be beneficial to the open source community as a whole to replace the starving artist —slash— burnt out maintainer trope with chilled out maintainers who have a good work/life balance.</p>
- <p>I think there’s also a lot of opportunity for lessons in Open Source Citizenship education as well. Instead of endless “Fuck you, fix my project” requests, there’s some hoops to jump through, some education, some reminder that there’s <strong>humans working for free</strong> on the other side of that comment box. <code>CONTRIBUTING.md</code> is a good step but contrast that with something like Discord’s welcome screen feature where you have to read and agree with a code of conduct before you can contribute. Anything to curb the entitlement and abuse is welcome. Onboarding people to the proper etiquette for filing a good bug report with proper repro steps or a reduced test case would go miles.</p>
- <p>There’s also another idea out there: a “Pay to Engage” model. You can read all the code, all the commits, all the issues, all the discussions, fork it, clone it, but if you want to engage and ask for help, you need to pay. Pay to Engage isn’t for every project and could hinder some projects, but it could unlock some sustainability.</p>
- <p>These are ideas, I probably have a million more. And you probably have a million as well. I’d love to read your blog posts about it. If you maintain an open source project, what’s been successful for you on the marathon? What’s worked? What hasn’t? My weary soul wants to know.</p>
- </article>
-
-
- <hr>
-
- <footer>
- <p>
- <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
- </svg> Accueil</a> •
- <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
- </svg> Suivre</a> •
- <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
- </svg> Pro</a> •
- <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
- </svg> Email</a> •
- <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
- </svg> Légal</abbr>
- </p>
- <template id="theme-selector">
- <form>
- <fieldset>
- <legend><svg class="icon icon-brightness-contrast">
- <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
- </svg> Thème</legend>
- <label>
- <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
- </label>
- <label>
- <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
- </label>
- <label>
- <input type="radio" value="light" name="chosen-color-scheme"> Clair
- </label>
- </fieldset>
- </form>
- </template>
- </footer>
- <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
- <script>
- function loadThemeForm(templateName) {
- const themeSelectorTemplate = document.querySelector(templateName)
- const form = themeSelectorTemplate.content.firstElementChild
- themeSelectorTemplate.replaceWith(form)
-
- form.addEventListener('change', (e) => {
- const chosenColorScheme = e.target.value
- localStorage.setItem('theme', chosenColorScheme)
- toggleTheme(chosenColorScheme)
- })
-
- const selectedTheme = localStorage.getItem('theme')
- if (selectedTheme && selectedTheme !== 'undefined') {
- form.querySelector(`[value="${selectedTheme}"]`).checked = true
- }
- }
-
- const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
- window.addEventListener('load', () => {
- let hasDarkRules = false
- for (const styleSheet of Array.from(document.styleSheets)) {
- let mediaRules = []
- for (const cssRule of styleSheet.cssRules) {
- if (cssRule.type !== CSSRule.MEDIA_RULE) {
- continue
- }
- // WARNING: Safari does not have/supports `conditionText`.
- if (cssRule.conditionText) {
- if (cssRule.conditionText !== prefersColorSchemeDark) {
- continue
- }
- } else {
- if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
- continue
- }
- }
- mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
- }
-
- // WARNING: do not try to insert a Rule to a styleSheet you are
- // currently iterating on, otherwise the browser will be stuck
- // in a infinite loop…
- for (const mediaRule of mediaRules) {
- styleSheet.insertRule(mediaRule.cssText)
- hasDarkRules = true
- }
- }
- if (hasDarkRules) {
- loadThemeForm('#theme-selector')
- }
- })
- </script>
- </body>
- </html>
|