A place to cache linked articles (think custom and personal wayback machine)
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

index.html 44KB

před 5 roky
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Corporations and OSS Do Not Mix (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://www.coglib.com/~icordasc/blog/2015/11/corporations-and-oss-do-not-mix.html">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Corporations and OSS Do Not Mix (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://www.coglib.com/~icordasc/blog/2015/11/corporations-and-oss-do-not-mix.html">Source originale du contenu</a></h3>
  445. <p>I have been working on Open Source Software (in one way or another) since 2011
  446. (just over 4 years since my first open source commit on a project). When I
  447. started writing open source software it was for fun. I was not a Computer
  448. Science/Engineering student. Programming was a hobby and open sourcing the
  449. code was fun and exciting. Eventually, I started maintaining Flake8, then
  450. Requests, then other things. Today, I'm a core developer of the following
  451. projects:</p>
  452. <p>And probably other projects that I've forgotten about. I've created
  453. (and still develop) the following projects:</p>
  454. <p>I'm was a core reviewer and driver for five projects in OpenStack (until
  455. recently when <a class="reference external" href="http://lists.openstack.org/pipermail/openstack-dev/2015-October/077876.html">I removed myself from 4 of those projects</a>).
  456. I am still a core reviewer for:</p>
  457. <p>I also contribute (a fair amount) and am often pinged for reviews on <a class="reference external" href="https://github.com/shazow/urllib3">urllib3</a>.</p>
  458. <p>Some of these projects are "owned" by one person and maintained by me (or me
  459. and other persons). In other words, the "owner" is absentee. Think of a
  460. landlord who does not collect the rent, or inspect the premises, or deal with
  461. tenants, or really any work.</p>
  462. <div class="section" id="working-on-projects-at-work">
  463. <h2>Working on projects at work</h2>
  464. <p>I've worked on a lot of projects. I continue to work on a lot of projects.
  465. Over the course of two jobs, only one has given me the ability to work on Open
  466. Source Software ... sometimes.</p>
  467. <p>OpenStack's Compute service, Nova, needed to perform URI validation as part of
  468. their JSON Schema validation but could not use the existing library because of
  469. licensing. Only because this was something important to my team, I was allowed
  470. to create <tt class="docutils literal">rfc3986</tt>. I continue to maintain that, but, in my free time.
  471. OpenStack uses, heavily:</p>
  472. <ul class="simple">
  473. <li>requests (and as a consequence chardet and urllib3)</li>
  474. <li>Flake8 (and transitively, pep8, pyflakes, and mccabe)</li>
  475. <li>Twine</li>
  476. <li>flake8-docstrings</li>
  477. </ul>
  478. <p>I've had opportunities to work on requests and Flake8 as a result of a few
  479. show-stopping bugs, but otherwise I don't work on any of the above projects
  480. during work. This isn't a break from what I'm used to, so I'm not trying to
  481. complain or anything like that. Would it be nice to be able to improve the
  482. software that powers our company and our product? Certainly, is there a
  483. serious need to do that? Not at the moment.</p>
  484. </div>
  485. <div class="section" id="working-on-projects-for-companies-that-don-t-employ-me">
  486. <h2>Working on projects for companies that don't employ me</h2>
  487. <p>Some of these projects are used by the US Federal Government, those and others
  488. are also used by some really large corporations (no I won't name names, I
  489. don't see a point). I sometimes get a thank you from individual developers at
  490. those companies, but those companies think nothing of just taking the software
  491. (which is fine because I licensed it permissively). That said, when there's a
  492. bug introduced in the package, those companies email me, ping me relentlessly
  493. in IRC, create duplicate issues, and do everything they can to (perhaps
  494. unintentionally) overload me. As soon as a bug affects them, they want it
  495. fixed <strong>immediately</strong>. If you don't fix it in 24 hours (because maybe you have
  496. a real life or a family or you're sick or any number of other very valid
  497. reasons) then the threats start.</p>
  498. <blockquote>
  499. "Well if you're not going to take this seriously, we'll have to start
  500. using another project."</blockquote>
  501. <p>Not once has a company said to me:</p>
  502. <blockquote>
  503. "This bug is costing us $X per day. Can we pay you $Y to focus on it and
  504. get a fix out as soon as possible?"</blockquote>
  505. <p>I've also never demanded this. It would be nice, but it never happens. So,
  506. what happens? Those bugs are fixed eventually. Sometimes those companies let
  507. their engineers submit a fix that is incredibly poor but it took them an hour
  508. and now they can whine at me for not merging it. Nevermind that it breaks the
  509. continuous integration checks that ran 30 seconds after they sent the PR. This
  510. is because the company wanted to invest as little time in the problem as
  511. possible so the person couldn't fix the tests, write new ones, or write a real
  512. fix. I don't blame the engineer, I blame their manager and their company. If
  513. the project is that important to them, they should have let the engineer spend
  514. a few hours, fix the bug the <em>right</em> way and follow the guidelines outlined in
  515. the contributor's documentation.</p>
  516. <p>Further, some of my projects (<tt class="docutils literal">github3.py</tt> in particular) tend to only ever
  517. actively benefit corporations - the corporation using it and GitHub. Neither
  518. ever tries to support me in its development. This is why I am also very
  519. conflicted about finding other maintainers for this project. I would love to
  520. find someone who could be paid by their employer to work on it, but I do the
  521. majority of the work on the project so it's hard to even know who to ask about
  522. that.</p>
  523. <p>In short, the joy and enthusiasm that I had when I started working on open
  524. source has been flattened. My attitude was naïve at best - this is fun and
  525. maybe I'm helping some other people do good and have fun too. This is also how
  526. a lot of my friends presently view their projects. Is it greedy of me to want
  527. them to continue to be able to have that perspective?</p>
  528. </div>
  529. <div class="section" id="other-people-s-experiences">
  530. <h2>Other people's experiences</h2>
  531. <p>Ashe Dryden has written an invaluable post about <a class="reference external" href="http://www.ashedryden.com/blog/the-ethics-of-unpaid-labor-and-the-oss-community">The Ethics of Unpaid Labor
  532. and the OSS Community</a>.
  533. This is a must read and it really hits home a bunch of very important points
  534. about the way we treat Open Source Software and its developers (e.g.,
  535. requiring that a developer have an active and colorful GitHub profile before
  536. considering them for a job).</p>
  537. <p>David MacIver recently decided they were <a class="reference external" href="http://www.drmaciver.com/2015/08/throwing-in-the-towel/">Throwing in the towel</a> for their project
  538. <a class="reference external" href="http://hypothesis.readthedocs.org/en/latest/">Hypothesis</a>.</p>
  539. <p>Eric Holscher, who co-founded <a class="reference external" href="https://readthedocs.org">Read the Docs</a> and
  540. <a class="reference external" href="http://conf.writethedocs.org/">Write the Docs</a>, has recently been
  541. <a class="reference external" href="https://twitter.com/ericholscher/status/658723665597456385">discussing</a> the
  542. economics of companies using open source software and contributing absolutely
  543. nothing back to the projects they use.</p>
  544. <p>Dr. Russell Keith-Magee, the president of the <a class="reference external" href="https://www.djangoproject.com/foundation/">Django Software Foundation</a>, gave <a class="reference external" href="https://youtu.be/mY8B2lXIu6g">this talk</a> at PyCon Australia. His key argument in this
  545. talk is that if open source projects had resources equivalent to closed source
  546. products, open source software would exceed any other project in quality. This
  547. talk is excellent and full of great examples.</p>
  548. <p>Cory Benfield, my very close friend and colleague on several of the projects I
  549. mentioned above, has <a class="reference external" href="https://lukasa.co.uk/2015/08/Funding_OSS/">also blogged on this topic</a>.</p>
  550. <p>No one is asking companies to endure a significant financial burden in order
  551. to contribute back. But all of these items are, predictably, ignored by the
  552. companies who seriously need these projects to work and remain production
  553. quality.</p>
  554. </div>
  555. <div class="section" id="when-companies-do-contribute">
  556. <h2>When companies do "contribute"</h2>
  557. <p>When companies do "contribute", it's often not in the best interest of the
  558. community, it isn't enough, or it's thoroughly misguided.</p>
  559. <div class="section" id="best-interest-of-the-community">
  560. <h3>Best interest of the community</h3>
  561. <p>OpenStack started as a collaboration between Rackspace and NASA; it was
  562. originally very operator focused. The project was used by tiny cloud operators
  563. and larger operators alike. All had a chance to voice grievances and work with
  564. developers to make things better. Somewhere along the way, the community
  565. became developers (who never deployed or operated OpenStack other than with
  566. DevStack) employed by large corporations working solely to forward the goals
  567. of those corporations. OpenStack isn't really something that was ever meant to
  568. be consumed by developers. Sure, the APIs are technically something a
  569. developer would use, but those are exactly how operators interact with the
  570. projects too. The developers who work on OpenStack don't mean to be harming
  571. the actual intended consumers, but if you keep an eye on discussions with
  572. operators, we (yes, I'm one of those developers) cause more problems than not
  573. out of sheer ignorance of the real users and how they <em>actually</em> use
  574. OpenStack. (To be clear, the <em>community</em> are the people who operate and
  575. maintain OpenStack clouds.)</p>
  576. <p>Generally speaking, though, companies can have engineers become involved in a
  577. project to scratch their own itch while also benefiting the community. These
  578. are not mutually exclusive results; they're just exceedingly rare results.</p>
  579. </div>
  580. <div class="section" id="it-isn-t-enough">
  581. <h3>It isn't enough</h3>
  582. <p>A lot of projects use sites like <a class="reference external" href="https://www.bountysource.com/">BountySource</a> to get paid to work on a bug on an open
  583. source project. <strong>Sometimes</strong>, companies will add a bounty to a bug. The
  584. largest bounty I've seen for any project I work on that accepts bounties has
  585. been $135 (USD). These values often do not reflect the true value to the
  586. company nor to the person fixing the bug. That said, sometimes you find a
  587. bounty <a class="reference external" href="https://www.bountysource.com/issues/25924774-add-ppc64le-port">like this one</a> where a
  588. company has added a significant amount to a bug. Those seem to be the
  589. exception rather than the rule, though.</p>
  590. <p>Other times, companies give a developer an hour to "make it go" which results
  591. in a situation like I described above. Allow me to expand: these will be
  592. companies that file a bug with as little detail as possible and then a fix
  593. that makes little sense and may appear to fix the bug but causes many others.
  594. After they have a fix, they stop responding to questions for more detail so it
  595. can be fixed appropriately. They often can't share a sample of how they're
  596. encountering the bug or anything like that.</p>
  597. </div>
  598. <div class="section" id="thoroughly-misguided">
  599. <h3>Thoroughly misguided</h3>
  600. <p>Some companies don't even bother giving engineering time to a project, or
  601. money to the developers working on the project. Instead they run well
  602. intentioned campaigns to increase activity for those projects by offering
  603. rewards to anyone for doing just about anything, regardless of value or merit.
  604. These rewards can be anything.</p>
  605. <p>One very recent such event promised a t-shirt if you sent 4 pull requests (via
  606. GitHub of course, because obviously <em>real</em> open source software would
  607. <strong>never</strong> be developed anywhere else) to open source projects. That was it.
  608. The pull request didn't need be merged, or to stay open for very long. It
  609. didn't need to contain any value at all. The event organizers contacted some
  610. projects <em>owners</em> asking if they could feature the projects. Now harken back
  611. to the paragraph where I explained that the owners of some of the projects I
  612. maintain are absentee. One of those was featured. That wasn't the only project
  613. I work on that that received hightened and lackluster attention from t-shirt
  614. seekers, but it was easily the one that received the highest traffic. So what
  615. happened was: the company contacted the owner who agreed but didn't tell me.
  616. The company never considered the fact that others might actually be doing the
  617. work of the project (and didn't think to check that with the API they're going
  618. to use to decide who gets a t-shirt). The company never talked to me in
  619. advance to, at minimum, warn me. (To be clear, the owner isn't blameless in
  620. this either, but I'm also not the only person who was in this position and
  621. complained about it. Perhaps I'm just loudest or have the largest platform.)</p>
  622. <p>Of all of the pull requests (on all the projects) that I received as a result
  623. of this event, some of them were merely diffs that looked like this:</p>
  624. <div class="highlight"><pre><span class="gh">diff --git a/ex.txt b/ex.txt.new</span>
  625. <span class="gh">index 5fe5360..e98e6b5 100644</span>
  626. <span class="gd">--- a/ex.txt</span>
  627. <span class="gi">+++ b/ex.txt.new</span>
  628. <span class="gu">@@ -1 +1 @@</span>
  629. <span class="gd">-foo bar bogus. Biz baz boo</span>
  630. <span class="gi">+foo bar bogus.. Biz baz boo</span>
  631. </pre></div>
  632. <p>No, really, I actually got a pull request that added a second period to the
  633. end of a sentence. I love encouraging and helping new contributors work on a
  634. project or otherwise aiding those new to open source in general, but how do
  635. you help someone who sends that pull request? Their commit message was "Update
  636. ex.txt". How do you help that person who clearly only has a goal of padding
  637. the number of PRs they sent for the month of October? Closing that pull
  638. request was a waste of my time, which is already stretched thin. I don't think
  639. that particular person was "trolling" (which is such an overused word as to be
  640. meaningless at this point), or otherwise behaving just in pursuit of their own
  641. amusement, but they were being inconsiderate.</p>
  642. <p>Further, let me reiterate that the company in question <strong>did</strong> contact
  643. someone. That in no way exonerates their borderline reckless behaviour. I
  644. actively mentor several people who are new to open source and their event
  645. consumed (in aggregate) a few days of my time which did not leave me enough
  646. time to work on real bugs in other projects or mentor those people as well as
  647. I could have.</p>
  648. </div>
  649. <div class="section" id="exceptions-to-the-rule-s">
  650. <h3>Exceptions to the rule(s)</h3>
  651. <p>There are exceptions to the rules above sometimes. There's one particular team
  652. at HP (actually they're now in HPE) that is entirely composed of some of the
  653. best open source developers I know of working full time on their areas of
  654. expertise. But, this is the only team I'm aware of at HPE that behaves like
  655. this. Other teams (I'm thinking specifically of their teams working on
  656. OpenStack and their former Helion product) are split between product work and
  657. upstream work and most of the time don't have enough time to dedicate to being
  658. upstream developers and reviewers.</p>
  659. <p>I would argue that while these sponsorships are good for the larger community,
  660. they're still a bit misguided. I trust each of these people to act in the best
  661. interest of their respective communities on that team at HPE, but what happens
  662. to them as soon as HPE decides funding that work is no longer beneficial or
  663. valuable? I don't have an answer to this, but I hope the answer is <em>not</em> that
  664. those developers are shown the door with a generous severance package. On a
  665. similar note, what happens if that developer decides they wish to explore
  666. other communities outside the reason they were hired? Is there room for growth
  667. or are their responsibilities narrowly defined enough that they have to quit
  668. to grow professionally?</p>
  669. <p>I'm asking these questions in the context of this one team at HPE but there
  670. are some similar teams at other companies and the same questions are valid for
  671. those teams as well. If you want an example of what I'm afraid of, just look
  672. for the TwitterOSS team (hint: their funding as a department was cut).</p>
  673. </div>
  674. </div>
  675. <div class="section" id="when-companies-open-source-a-project">
  676. <h2>When companies open source a project</h2>
  677. <p>There's also a separate pattern in the larger community where a company that
  678. already has some reputation in the community decides to open source a project
  679. that was previously just something they had initially developed for internal
  680. use. If these companies dedicate resources to the upkeep of the project and
  681. development of a community there tend to be two possible outcomes:</p>
  682. <ol class="arabic simple">
  683. <li>The company refuses to expand the core development team with non-employees</li>
  684. <li>The company abandons the project and allows non-employees to take over the
  685. entirety of the maintenance burden while continuing to reap the PR benefits
  686. and failing to credit those people or support them in any manner.</li>
  687. </ol>
  688. <p>There are also rarer cases where people who contribute heavily to those
  689. projects are offered jobs to continue their work as an employee, but those
  690. seem to be fairly rare.</p>
  691. </div>
  692. <div class="section" id="why-do-companies-behave-this-way">
  693. <h2>Why do companies behave this way?</h2>
  694. <p>I have heard a myriad of reasons companies behave this way. I don't have the
  695. complete answer, but one important point is that there is toxicity in the
  696. community, its leaders, and or its contributors, and the companies have
  697. learned their behavior from this toxicity.</p>
  698. <div class="section" id="open-source-software-is-full-of-toxic-people">
  699. <h3>Open source software is full of toxic people</h3>
  700. <p>This certainly shouldn't be a surprise at this point. I would guess that it is
  701. safe to say that pretty much every person (including myself, I'm certainly not
  702. exempt from this) has had bad days and reacted poorly when dealing with the
  703. community, contributors, colleagues, etc. These are not excuses and these
  704. events can (and often do) shape the behaviours of the community and those
  705. observing it.</p>
  706. <p>A close friend of mine, Paul Tagliamonte, was involved in the discussion about
  707. Debian's switch to systemd. He received <strong>at least</strong> 3 death threats due to
  708. his participation. In what world is this acceptable behaviour for a community?
  709. What about developers who have their addresses and the information of their
  710. loved ones posted on 4chan and other "forums"? Why don't we fight this more?</p>
  711. <p>Any company that has involved itself (or its employees) with Linux Kernel
  712. development has probably come away with a very intensely sour taste in their
  713. mouth and a jaded view of how to effectively contribute to an open source
  714. project. In fact, I wouldn't be surprised to learn that these companies
  715. witnessed significant churn in the engineering teams working with that
  716. community.</p>
  717. <p>They're also certainly not the only community struggling with this. Companies
  718. need to be involved, but just like other contributors, they need to be assured
  719. that they will be taken seriously and treated equally. Some projects work to
  720. actively alienate corporations trying to contribute because of ideology. This
  721. is not the path that will lead us to sustainable open source software
  722. development and companies that can contribute responsibly.</p>
  723. </div>
  724. </div>
  725. <div class="section" id="what-needs-to-change">
  726. <h2>What needs to change</h2>
  727. <p>Too much for me to clearly or effectively enumerate without missing things. So
  728. let me give a high level list of things that I see as being incredibly
  729. problematic and maybe I'll expound on them (or a subset) if I still have the
  730. emotional energy to do so.</p>
  731. <ol class="arabic simple">
  732. <li>Companies need to do more for the projects they use (financially, by
  733. engineers who can contribute to the project appropriately during their
  734. normal working hours, donating services, or some other way)</li>
  735. <li>Companies that already contribute resources in one way or another need to
  736. check that what they're doing is not only in their best interest (or
  737. perhaps not in their best interest at all). No, really, the good of <em>the
  738. project</em> should be the focus of any contribution. If your goal is to
  739. improve something <em>only</em> for the company, then that isn't a contribution in
  740. good faith.</li>
  741. <li>Companies looking for publicity and events that they can tout as their
  742. support of open source software, need to actually employ open source
  743. developers who know the pain that those events will inflict. Not a single
  744. maintainer has ever said "I don't care about the quality, just give me a
  745. flood of new contributions that I need to code review, give feedback, and
  746. hope that person actually acts on the feedback." Not once. I was linked to
  747. <a class="reference external" href="http://awkwardzombie.com/index.php?page=0&amp;comic=013111">this webcomic</a>
  748. recently and it aptly describes this approach.</li>
  749. <li>If a company has an engineer test a fancy new feature for a project, that
  750. engineer needs to test more than just their own use cases to give effective
  751. or valuable review. (See also the following tweets from Jeff Forcier:
  752. <a class="reference external" href="https://twitter.com/bitprophet/status/660943465547599872">https://twitter.com/bitprophet/status/660943465547599872</a>,
  753. <a class="reference external" href="https://twitter.com/bitprophet/status/660943804250263552">https://twitter.com/bitprophet/status/660943804250263552</a>,
  754. <a class="reference external" href="https://twitter.com/bitprophet/status/660943975738556416">https://twitter.com/bitprophet/status/660943975738556416</a>,
  755. <a class="reference external" href="https://twitter.com/bitprophet/status/660944140641763328">https://twitter.com/bitprophet/status/660944140641763328</a> in which he relays
  756. a story of an important PR that people claimed worked without really deeply
  757. testing it.)</li>
  758. <li>Companies that use open source software should strive to hire some,
  759. if not all (not all in one place either), of those people that maintain the
  760. software to work on the project. And no, I do not expect those people to
  761. work 100% of their time on that project. That's unreasonable. They should
  762. be treated like adults though and allowed to spend what they see as an
  763. appropriate amount of time working on the project versus other projects for
  764. the company. Trying to quanitfy/limit the amount of time leads to conflict
  765. and strife and unhappy management and employees. It doesn't work and it's
  766. not a long term, maintainable solution.</li>
  767. <li>Alternatively, instead of hiring those developers to hire the existing core
  768. developers, reviewers, and maintainers, those companies can buy training on
  769. how to effectively contribute and participate in upstream projects. That
  770. said, I doubt there's anyone who can train a person in empathy.</li>
  771. <li>Companies need to stop encouraging and allowing their engineers to be
  772. abrasive, abusive, or insulting when reporting bugs or contributing changes
  773. to projects. This was admittedly more of a problem before I added Codes of
  774. Conduct to projects, but I still see this on other people's projects. (This
  775. happened 2 years ago on a bug report where the company upgraded from an
  776. ancient version of our project to the latest and greatest and found some
  777. usecase that apparently only they had that broke. The vitriol in their
  778. replies and their behaviour should have resulted in them being reprimanded
  779. by their managers for behaving that way while at work.)</li>
  780. <li>Companies need to have realistic expectations of the work-life balance of
  781. open source maintainers. Open source software is unpaid labor for so many
  782. of us. It <em>is</em> work. Many of us working on successful projects take it very
  783. seriously. It is stressful. It is emotionally draining. Sometimes we don't
  784. have the energy to fix your problem as soon as you think it should be
  785. fixed. Sometimes we're on vacation. Sometimes we're sick or taking care of
  786. loved ones. Behaving as if we're your employee that you can just boss
  787. around is not acceptable. If you want that relationship with us, hire us to
  788. work on the project. (Hint: If you act like this, I will never work for you
  789. because it is very apparent your management does not understand what a real
  790. life is or how a work-life balance needs to be managed.)</li>
  791. <li>Companies need to realize that not all open source authors or maintainers
  792. view their projects the same way. For many of us, we scratched an itch, we
  793. are not developing a product. We often do not want our hobbies turned into
  794. work because then we no longer have an outlet or a place to just have fun.
  795. The project may be <em>serious business</em> for you, but that may not be how
  796. others view it.</li>
  797. <li>Money isn't everything. Whether you're a bootstrapped start-up or a company
  798. that is publicly traded with stock values in the hundreds of dollars, money
  799. isn't everything. Instead of placing $5000.00 on a bug, develop a
  800. relationship with the community. Sometimes a heartfelt gift is more
  801. meaningful than a large sum of money. I know some people who'd rather have
  802. games purchased for them off their Steam wishlist. Other people would love
  803. to get things from their Amazon wishlist. Know the people who develop the
  804. software that allow you to make the money you make and respect them.</li>
  805. <li>Acknowledge the projects somewhere on your website, product, wherever. This
  806. one is simple, just say "This is powered by ...". This gives projects
  807. credibility and that gains users which means another company that can
  808. afford it might hire that person to work on that project.</li>
  809. <li>Companies that open source something need to adopt a Code of Conduct
  810. immediately and from the start. And preferably, if they can, companies
  811. should sponsor and contribute to other projects that have Codes of Conduct
  812. (preferably real ones, not the crap the Linux Kernel has adopted).</li>
  813. <li>Companies that open source a project and then abandon it need to publicly
  814. acclaim the people taking over the project and make a clear change in
  815. ownership. Creating a third-party organization that includes everyone
  816. actively involved in the project is the best plan and the one that will
  817. allow those non-employee maintainers to manage their time and commitments
  818. while being able to be recognized for their hard work, passion, and
  819. dedication.</li>
  820. <li>More communities need to adopt Codes of Conduct and be more mindful about
  821. how their actions affect current participation of corporate and
  822. non-corporate contributors while coloring the future reputation of the
  823. project. Developers move on but first impressions do not. As new developers
  824. cycle onto projects, they may be unaware of past events and may be
  825. metaphorically shooting themselves in the feet.</li>
  826. <li>Conversely, companies need to continuously strive to take the high ground
  827. and continuously re-evaluate projects and their involvement (or lack
  828. thereof) in the project.</li>
  829. <li>Tons of things I can't think of at this very moment. Go read other articles
  830. about this. There are tons.</li>
  831. </ol>
  832. </div>
  833. <div class="section" id="concluding-some-things">
  834. <h2>Concluding some things</h2>
  835. <p>As with all of my posts on this web log, there is no comments section. If
  836. you'd like to discuss this with me, I would encourage you to email me. (You
  837. can find my address on my <a class="reference external" href="https://github.com/sigmavirus24">GitHub profile</a>.) If you would rather discuss this in a
  838. briefer and more public fashion you can also discuss this with me on <a class="reference external" href="https://twitter.com/sigmavirus24">Twitter</a>. <strong>Keep in mind that I've been really
  839. working on keeping a very serious work-life balance so my responses will
  840. likely be delayed if they occur at all.</strong></p>
  841. <p>I also fully reserve the right to take points from this post and write
  842. follow-up posts in much greater detail. If you take the time to send me an
  843. email or a tweet, I may also desire to use that as a discussion point in a
  844. future post. Be prepared for my asking permission to quote you, even if doing
  845. so anonymously.</p>
  846. <hr class="docutils"/>
  847. <p>I would like to extend specific and sincere gratitude to <a class="reference external" href="http://ceastapleton.com/">Cea Stapleton</a>, <a class="reference external" href="https://lukasa.co.uk/">Cory Benfield</a>, and
  848. <a class="reference external" href="https://pault.ag/">Paul Tagliamonte</a> for their thoughtful, critical, and
  849. crucial review and feedback while I wrote this piece.</p>
  850. </div>
  851. </article>
  852. </section>
  853. <nav id="jumpto">
  854. <p>
  855. <a href="/david/blog/">Accueil du blog</a> |
  856. <a href="http://www.coglib.com/~icordasc/blog/2015/11/corporations-and-oss-do-not-mix.html">Source originale</a> |
  857. <a href="/david/stream/2019/">Accueil du flux</a>
  858. </p>
  859. </nav>
  860. <footer>
  861. <div>
  862. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  863. <p>
  864. Bonjour/Hi!
  865. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  866. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  867. </p>
  868. <p>
  869. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  870. </p>
  871. <p>
  872. Voici quelques articles choisis :
  873. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  874. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  875. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  876. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  877. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  878. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  879. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  880. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  881. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  882. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  883. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  884. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  885. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  886. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  887. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  888. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  889. </p>
  890. <p>
  891. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  892. </p>
  893. <p>
  894. Je ne traque pas ta navigation mais mon
  895. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  896. conserve des logs d’accès.
  897. </p>
  898. </div>
  899. </footer>
  900. <script type="text/javascript">
  901. ;(_ => {
  902. const jumper = document.getElementById('jumper')
  903. jumper.addEventListener('click', e => {
  904. e.preventDefault()
  905. const anchor = e.target.getAttribute('href')
  906. const targetEl = document.getElementById(anchor.substring(1))
  907. targetEl.scrollIntoView({behavior: 'smooth'})
  908. })
  909. })()
  910. </script>