Repository navigation
Licensing, code of conduct, and contributing guide #205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
3f13b65
Keep one code of conduct, at the root, and render it on the site
DZPM 0fe79e5
Add a contributing guide, and move the pull request steps into it
DZPM 77de701
Add the MIT licence for the code and a licensing file for the rest
DZPM 48d7433
Point the README and the contributing guide at the licences
DZPM d65f08b
Use the serial comma in the licensing texts
DZPM 903e3ec
Add the missing serial comma in the README licence section
DZPM 7ed1696
Move the code of conduct to CC BY-SA 4.0
DZPM 6fc2dbc
Say what is true of edition, not of the branch this came from
DZPM 81d9d53
Merge remote-tracking branch 'origin/edition' into work/governance
DZPM 22fe7f6
Tell a person how to change or remove their own card
DZPM c4ccf74
Add AGENTS.md, for the agents that work on this repository
DZPM 317db39
Correct the page count in AGENTS.md
DZPM 74472ae
Index the decisions, where they are instead of copying them
DZPM c37682e
Merge remote-tracking branch 'origin/edition' into work/governance
DZPM File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| # AGENTS.md | ||
|
|
||
| Guidance for AI coding agents working on pybcn.org, the website of Associació | ||
| Python Barcelona. | ||
|
|
||
| Read [CONTRIBUTING.md](CONTRIBUTING.md) as well. This file covers only what an | ||
| agent gets wrong that a human would not, and what this repository does | ||
| differently from a default Hugo site. | ||
|
|
||
| ## Build and run | ||
|
|
||
| ```sh | ||
| bin/install # downloads the pinned Hugo binary, verifies its SHA256 | ||
| bin/serve # dev server, Hugo's default :1313 | ||
| bin/build # writes to docs/ | ||
| bin/hugo --quiet -d /tmp/out # the binary directly | ||
| ``` | ||
|
|
||
| **The Hugo binary lives at `bin/hugo` and is gitignored.** `bin/helpers` prefers | ||
| it over anything on `$PATH`, and checks the version from `.hugo-version`. | ||
|
|
||
| **Do not `pip install hugo`.** That PyPI package now requires a Go toolchain and | ||
| fails. `bin/install` fetches the official release binary instead. | ||
|
|
||
| A clean build produces **109 HTML pages**: 53 Hugo-generated and 56 copied | ||
| from `static/archives/`. Recount rather than trusting this line: the number | ||
| moves with the content. It was 317 until #202 stopped publishing the 206 | ||
| person and sponsor pages that nothing linked to, which is how quickly a | ||
| figure like this goes stale. | ||
|
|
||
| ## Traps that have already cost time | ||
|
|
||
| **TOML key placement.** `config.toml` ends with nested `[params.social_items...]` | ||
| tables. A key appended at the end of the file lands **inside the last table** and | ||
| silently does nothing. Put top-level keys near `theme =`, and verify by building | ||
| and checking the output, not by reading the file. | ||
|
|
||
| **`merge.ff = only`.** Any local merge needs `--no-ff`. A failed merge here reports | ||
| "Not possible to fast-forward", which is not a conflict. | ||
|
|
||
| **`unsafe=true` in `[markup.goldmark.renderer]`.** Raw HTML in front matter | ||
| and page bodies renders unescaped. Two content files still carry it, | ||
| `content/events/pyday_bcn/pyday_bcn_2018.md` and `pyday_bcn_2019.md`, which | ||
| are pre-Hugo programmes pasted in as tables. So **assume any content field | ||
| can inject HTML**, and never add a field that reaches a template through | ||
| `safeHTML`. `bin/check-html-safety` rejects dangerous markup in content and | ||
| `bin/check-rendered` checks the built pages; both run on every pull request. | ||
|
|
||
| **`resources/_gen/` and `docs/` are build output and are gitignored.** They | ||
| used to be tracked, so a build dirtied the tree and a pull request carried | ||
| hundreds of regenerated files. If `git status` shows either of them, you are | ||
| on a branch from before that change. | ||
|
|
||
| **`master` is not a source branch.** It is the built site, force-pushed as an | ||
| orphan commit by the deploy workflow. The default branch is **`edition`**. | ||
|
|
||
| **Images in `static/` cannot be processed by Hugo.** They must be under `assets/` | ||
| for `resources.Get` and `.Resize` to work. This is why the site once shipped 8.97 | ||
| MB of photographs on a single page. | ||
|
|
||
| ## Rules that are not style preferences | ||
|
|
||
| These come from decisions with reasons behind them. Breaking them creates a | ||
| problem somebody else has to find. | ||
|
|
||
| **Never store a role that can be computed.** `speaker` and `host` are derived from | ||
| the talk and meetup records. Writing them into a person's front matter guarantees | ||
| they will eventually contradict the data. | ||
|
|
||
| **A person attribution requires human verification.** Talk records carry | ||
| `source` and `confidence`. **Only a human-verified record may create a person page | ||
| or link a speaker name.** A record with `confidence: medium` or `low` renders the | ||
| talk with an "unconfirmed" marker and leaves the speaker name as plain text. | ||
|
|
||
| This is not a style rule. Publishing an unverified claim about a named person | ||
| fails the accuracy principle of the GDPR, and the confidence field then documents | ||
| that we knew. | ||
|
|
||
| **Never merge two people on a first-name match.** The existing ids include bare | ||
| first names (`david`, `alberto`, `jordi`, `ricardo`) that already collide with | ||
| fuller names on the site. When in doubt, leave both and flag it. | ||
|
|
||
| **Do not promote hosting to a role.** Meetup's `eventHosts` field is a tool | ||
| attribute, not a title. Hosting one meetup is not being an organizer. | ||
|
|
||
| **RSVPs are not attendance.** `attendedCount` is zero on 205 of 207 events, so the | ||
| only figure available is who said yes on Meetup. Render it as registrations. | ||
|
|
||
| **No personal data beyond what is already published.** Never render email | ||
| addresses, phone numbers, or social handles extracted from old event | ||
| descriptions, even though they are present in the source data. Never derive a | ||
| person's attributes from the event they spoke at. | ||
|
|
||
| **Person ids** are `firstname-surname`, kebab-case, accents stripped. A rename | ||
| carries an `aliases` entry **and** updates every reference in `content/events/` in | ||
| the same commit. Skipping the second half silently drops the person from those | ||
| pages, and that bug has been live on this site. | ||
|
|
||
| ## Commits | ||
|
|
||
| **No AI attribution.** No `Co-Authored-By` trailer, no generated-with footer, no | ||
| model byline. Commits read as authored by the person who made them. | ||
|
|
||
| **Never use the em dash character (U+2014).** Use a comma, a colon, parentheses, or | ||
| restructure. | ||
|
|
||
| Write in plain, factual English. Say what changed, why, and what you verified. | ||
| **If part of the work is unfinished, say so in the commit message**, with what | ||
| blocks it. A commit that claims more than it did is worse than one that admits a | ||
| gap. | ||
|
|
||
| ## Verify, do not assert | ||
|
|
||
| This repository has a history of changes that looked right and were not. The | ||
| build succeeding proves very little: a missing sponsor page, a person id that does | ||
| not match its filename, and a broken image URL all build cleanly. | ||
|
|
||
| So: | ||
|
|
||
| - Build and grep **the generated HTML**, not the templates. | ||
| - Give before and after numbers for anything you claim to have fixed. | ||
| - When you cannot verify something without a browser or a screen reader, **say | ||
| that** rather than asserting it works. | ||
|
|
||
| Two checkers exist and both are cheap to run: | ||
|
|
||
| ```sh | ||
| bin/check-content # front matter, ids, cross-references (needs pyyaml) | ||
| bin/check-html-safety # dangerous raw HTML in content | ||
| ``` | ||
|
|
||
| ## Things you cannot do | ||
|
|
||
| **Do not push, open pull requests, or comment on GitHub.** Leave your work as a | ||
| local branch. Opening it is a human decision, taken per item. | ||
|
|
||
| **Do not change DNS, repository settings, or anything outside the working tree.** | ||
|
|
||
| **Do not install software.** If a task genuinely needs a tool that is absent, say | ||
| so and stop, rather than working around it with something that produces a | ||
| plausible but different result. | ||
|
|
||
| ## Where things are | ||
|
|
||
| | Path | What | | ||
| |---|---| | ||
| | `content/people/` | One markdown file per person, keyed by `id` | | ||
| | `content/events/` | PyDay BCN, PyDataBCN, and other events, with their agendas in front matter | | ||
| | `content/sponsors/` | One file per sponsor | | ||
| | `themes/pybcn_theme/` | The theme, **vendored in-tree**, not a submodule | | ||
| | `themes/pybcn_theme/layouts/partials/` | Most of the interesting template logic | | ||
| | `static/archives/` | Verbatim mirrors of pre-Hugo sites, copied unprocessed | | ||
| | `data/` | Tables the templates read: `roles.yaml` maps a heading to a role, `role_emoji.yaml` a role to a glyph | | ||
| | `bin/` | Setup and build scripts, plus the gitignored Hugo binary | | ||
| | `.hugo-version` | The pinned Hugo version, single source of truth | | ||
|
|
||
| The checks, which are what a pull request has to pass: | ||
|
|
||
| | Script | What it rejects | | ||
| |---|---| | ||
| | `bin/check-content` | A broken reference, a photo that is not square, a source far larger than the build asks for, a field that no longer exists | | ||
| | `bin/check-html-safety` | Dangerous raw HTML in content, with an allowlist for the legitimate embeds | | ||
| | `bin/check-rendered` | The same, on the built pages, plus any `http://` URL. Run it against a directory you built, never against `public/` while a dev server is writing there | | ||
|
|
||
| The join between a person and an event is `where $pages ".Params.id" "eq" $person` | ||
| in `partials/people-grid.html`. That pattern is how everything cross-references, | ||
| and it fails silently when an id does not match. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Code of Conduct | ||
|
|
||
| PyBCN is dedicated to providing a respectful, harassment-free community for | ||
| everyone. We do not tolerate harassment or bullying of any community member in | ||
| any form. This does not only extend to members to local PyBCN communities, | ||
| but to anyone who chooses to become involved in the larger PyBCN community of | ||
| users, developers and integrators through events or interactions. | ||
|
|
||
| Harassment includes offensive verbal/electronic comments related to personal | ||
| characteristics or choices, sexual images or comments in public or online | ||
| spaces, deliberate intimidation, bullying, stalking, following, harassing | ||
| photography or recording, sustained disruption of talks, IRC chats, electronic | ||
| meetings, physical meetings or other events, inappropriate physical contact, or | ||
| unwelcome sexual attention. Participants asked to stop any harassing or | ||
| bullying behavior are expected to comply immediately. | ||
|
|
||
| If a participant engages in harassing behavior, representatives of the | ||
| community may take reasonable action they deem appropriate, including warning | ||
| the offender, expulsion from any PyBCN event, or expulsion from mailing | ||
| lists, IRC chats, discussion boards and other electronic communications | ||
| channels to resolve the issue. This may include expulsion from PyBCN Meetup | ||
| group membership. | ||
|
|
||
| If you are being harassed, notice that someone else is being harassed, or have | ||
| any other concerns, please act to intercede or ask for help from any member of | ||
| the PyBCN community, IRC chat admins, website admins, or | ||
| organizers/representatives of any physical events put on under the auspices of | ||
| PyBCN. | ||
|
|
||
| This Code of Conduct has been adapted from the | ||
| [PyLadies](https://www.pyladies.com/CodeOfConduct/) one, which is licensed | ||
| under a | ||
| [Creative Commons Attribution-Share Alike 3.0 Unported license](https://creativecommons.org/licenses/by-sa/3.0/), | ||
| and is licensed under a | ||
| [Creative Commons Attribution-ShareAlike 4.0 International license](https://creativecommons.org/licenses/by-sa/4.0/). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,172 @@ | ||
| # Contributing to the PyBCN site | ||
|
|
||
| This repository holds the source of [pybcn.org](https://pybcn.org/), the site | ||
| of the Python Barcelona association, built with [Hugo](https://gohugo.io). A | ||
| change goes through a pull request against the `edition` branch, and this | ||
| guide says how. The [README](README.md) documents the site itself: the content | ||
| fields, the layouts, and what each check looks for. | ||
|
|
||
| ## Code of conduct | ||
|
|
||
| The PyBCN [Code of Conduct](CODE_OF_CONDUCT.md) applies to every contribution: | ||
| a pull request, an issue, a review, and the discussion around them. It is the | ||
| same text the site publishes at | ||
| [pybcn.org/pybcn_association/coc/](https://pybcn.org/pybcn_association/coc/), | ||
| which renders that file. | ||
|
|
||
| ## Licence | ||
|
|
||
| The code of the site is under the [MIT License](LICENSE) and the content is | ||
| under [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). | ||
| [LICENSING.md](LICENSING.md) says which paths each one covers, and which paths | ||
| are not licensed at all: the photographs of people, the person pages, the | ||
| sponsor logos, the association's own logos, the third-party libraries, and the | ||
| archived sites. | ||
|
|
||
| A pull request is a contribution under those terms. A change to a template, a | ||
| script, or a stylesheet is offered under the MIT License, and a change to the | ||
| text of a page is offered under CC BY-SA 4.0. Your own page under | ||
| `content/people/` and your photo are different: you keep every right in them, | ||
| and you give PyBCN permission to publish them on this site, which you can | ||
| withdraw. | ||
|
|
||
| ## Which branch | ||
|
|
||
| Open the pull request against `edition`. It is the default branch and it holds | ||
| the source. `master` holds the built site: the `github-pages` workflow writes | ||
| it on every merge to `edition` and replaces its history each time, so nothing | ||
| is edited there, and a change made on `master` is lost on the next deploy. | ||
|
|
||
| ## Your own card | ||
|
|
||
| **You do not need Git, GitHub, or any of the rest of this file.** | ||
|
|
||
| If you have spoken at one of our events, or you organise with us, you may have | ||
| a card on the [organizers page](https://pybcn.org/pybcn_association/organizers/) | ||
| or on the page of the event. Clicking it opens what the site holds about you. | ||
| To change any of it, or to have it removed, **send an email to | ||
| <pybcn@googlegroups.com> saying what to change**. That is enough. We do not ask | ||
| for identity documents to correct or remove your own name. | ||
|
|
||
| If you would rather do it yourself, every card is a file under | ||
| `content/people/`, named after the person. Click the pencil icon on GitHub, | ||
| change the text, and GitHub walks you through opening a pull request. | ||
|
|
||
| ### What is on your card | ||
|
|
||
| Your name, the role you held, and the events you appeared at. The list of | ||
| events is computed from the pages that list you, so it is not edited on your | ||
| card: if an event is missing or wrong, tell us and we fix the event page. | ||
|
|
||
| Everything else is yours to give or withhold: | ||
|
|
||
| | Field | What it does | | ||
| |---|---| | ||
| | `photo` | A square image, under `themes/pybcn_theme/assets/images/people/` | | ||
| | `linkedin`, `github`, `twitter`, `site` | Links under your name | | ||
| | the body of the file | The bio, one paragraph or several | | ||
|
|
||
| Whoever did not want a photo does not have one, and the card works without it. | ||
|
|
||
| ### If you would rather not appear | ||
|
|
||
| Write to <pybcn@googlegroups.com> and we remove the card. We will not argue | ||
| about it. | ||
|
|
||
| Be aware of what removal can and cannot do, because this is a public | ||
| repository. We remove the card from the site and from the build, and we ask | ||
| search engines and the Internet Archive to drop their copies. We cannot remove | ||
| it from the Git history, and we cannot remove copies other people have already | ||
| made. | ||
|
|
||
| If that is not acceptable to you, tell us **before** we publish. We would | ||
| rather not publish a card than publish one we cannot properly withdraw. | ||
|
|
||
| ## Add content without writing code | ||
|
|
||
| Most changes to this site are content: a person, a sponsor, an event. Each one | ||
| is a Markdown file with a front matter, and the README documents the fields. | ||
| Edit the file on GitHub, or clone the repository and follow the steps below. | ||
|
|
||
| - **A person** (an organizer, a speaker, a mentor): copy a file under | ||
| `content/people/` and edit it. The front matter carries `id`, which has to | ||
| match the file name, `name`, `photo`, the role at PyBCN, and the links to | ||
| the person's own profiles. The bio goes in the body. Leave out any field the | ||
| person does not have. The photo goes under | ||
| `themes/pybcn_theme/assets/images/people/` and has to be square, see | ||
| [Person photos](README.md#person-photos). | ||
| - **A sponsor**: run `bin/hugo new sponsors/my-sponsor.md` and fill the four | ||
| fields listed in [How to add a new sponsor](README.md#how-to-add-a-new-sponsor). | ||
| The logo goes under `themes/pybcn_theme/assets/images/sponsors/`. Then list | ||
| the sponsor on the sponsors page, or on the event, that shows it. | ||
| - **An event**: copy the previous edition under `content/events/`, for example | ||
| `content/events/pyday_bcn/pyday_bcn_2025.md`, and edit it. The sections, the | ||
| agenda and the people grids are described in | ||
| [Event page](README.md#event-page). An event lists its people and sponsors by | ||
| their `id`, so add those files first. | ||
|
|
||
| `bin/check-content` reads every person, sponsor and event file. The pull | ||
| request fails when a field is empty, an `id` does not match the file name, a | ||
| declared photo is missing, or an event names a person or a sponsor that does | ||
| not exist. Run it locally, step 5 below, to see what it would say. | ||
|
|
||
| To report a problem with the site, open an issue and give the URL of the page. | ||
|
|
||
| ## Make the change | ||
|
|
||
| Nothing is pushed to `edition` directly. | ||
|
|
||
| 1. Clone the repository. `git clone --single-branch --branch edition` is enough | ||
| and skips the built site, which lives on its own branch. | ||
| 2. Run `bin/install`. It downloads the pinned Hugo binary into `bin/hugo` and | ||
| verifies its checksum. You do not need Python, Go, or npm for this step. | ||
| 3. Run `bin/serve` to see the site at `http://localhost:1313` while you work. | ||
| 4. Make the change. | ||
| 5. Run the three checks locally, so you find what the pull request would find: | ||
|
|
||
| ``` | ||
| pip install pyyaml pillow | ||
| bin/check-content | ||
| bin/check-html-safety | ||
| bin/hugo --minify -D -d public && bin/check-rendered | ||
| ``` | ||
|
|
||
| Pillow is only needed for the black and white photo check. Without it the | ||
| rest still runs and the check says it was skipped, so a missing Pillow | ||
| never fails a build for the wrong reason. | ||
|
|
||
| 6. Open the pull request against `edition`. | ||
|
|
||
| ## What the pull request goes through | ||
|
|
||
| The `pr-checks` workflow runs the same checks on your branch, plus a build and | ||
| a link check. **All of them have to pass**, and one approving review is needed | ||
| before the pull request can be merged. | ||
|
|
||
| What each check is for: | ||
|
|
||
| | Check | Fails when | | ||
| |---|---| | ||
| | Build the site | Hugo cannot build, or emits a warning | | ||
| | `bin/check-content` | Front matter does not parse, a person `id` does not match its filename, an id is duplicated, a declared photo is missing, an event references a person or sponsor that does not exist, a social URL has the wrong shape, or a field is empty. It warns, without failing, about a photo that is too small or has no colour | | ||
| | `bin/check-html-safety` | Content carries raw HTML that turns a content change into script execution, a redirect, a credential prompt, or a page overlay. See [Content safety check](README.md#content-safety-check) | | ||
| | `bin/check-rendered` | The built pages carry that same markup, which catches a template that produces it even when no content file does, or they link to anything over `http`. See [Rendered page check](README.md#rendered-page-check) | | ||
| | Check the links | Reported, never blocking, because external sites rate-limit | | ||
|
|
||
| A merge to `edition` deploys the site. The `github-pages` workflow builds it and | ||
| publishes the result, so a change is live within a few minutes of the merge. | ||
|
|
||
| ## Review by the web team | ||
|
|
||
| `.github/CODEOWNERS` lists the paths where a change reaches every page of the | ||
| site, or reaches money, or reaches the deploy: `.github/`, `bin/`, | ||
| `config.toml`, `layouts/`, `static/`, `themes/`, `CNAME`, the association | ||
| pages under `content/pybcn_association/`, `CODE_OF_CONDUCT.md`, and the | ||
| sponsor and event files under `content/sponsors/` and `content/events/`. | ||
|
|
||
| A pull request that touches one of those paths requests a review from | ||
| `@pybcn/web` automatically, and the branch protection on `edition` requires | ||
| it, so the pull request waits until a member of that team approves it. A | ||
| person's file under `content/people/` is not on the list on purpose: a speaker | ||
| edits their own page and needs no organizer for that, only the one approving | ||
| review every pull request needs. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be updated after the merge of #206? After all, Pillow is needed for the fit-sources script