<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Sarah Abderemane's Website</title><link href="https://sarahabd.com/" rel="alternate"></link><link href="https://sarahabd.com/feeds/rss.xml" rel="self"></link><id>https://sarahabd.com/</id><updated>2026-05-06T18:00:00+02:00</updated><entry><title>Me and Mentorship</title><link href="https://sarahabd.com/blog/me-and-mentorship" rel="alternate"></link><published>2026-05-06T18:00:00+02:00</published><updated>2026-05-06T18:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2026-05-06:/blog/me-and-mentorship</id><summary type="html">&lt;p class="first last"&gt;Mentoring is a great way to learn, some of my reflexions on mentoring and contributing to open source projects.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there.. it’s been a while as usual… 😄&lt;/p&gt;
&lt;p&gt;Today I would like to talk about mentoring. It’s been a constant in my
life. I have been on both sides: mentee and mentor. I can tell you that
you learn so much from this exchange.&lt;/p&gt;
&lt;p&gt;Being a mentee is a way to learn from an expert or just people who know
more than yourself. Those people you truly admire for their work. The
mentees don’t even always tell how much they admire their mentors.&lt;/p&gt;
&lt;p&gt;On the reverse, being a mentor is a good way to learn how to share your
knowledge the best way. You watch the person you’re mentoring grow and
make their own decisions, without ever having to ask you for advice in
the end, because you’ve given them the tools to find the answers on
their own. One day, perhaps, they’ll take the time to thank you, because
without even realizing it, you’ve changed their life.&lt;/p&gt;
&lt;p&gt;It’s crazy, isn’t it? I love mentoring because it’s a special and unique
exchange: you feel close to the other person, because when you’re a
mentor, you see a younger version of yourself in your mentee, and the
mentee sees you as what they might one day become. I’m sure many people
don’t see mentoring exactly the way I do, but it’s an extremely
rewarding experience.&lt;/p&gt;
&lt;p&gt;Mentoring is a great way to learn, whether you’re the mentee or the
mentor. Yes, mentors learn from the experience as well. How can you make
sure your mentee has understood what you meant? How can you clearly
explain something that seems obvious to you to the person sitting across
from you? The mentee’s questions help us discover aspects we had never
considered before. There is so much to learn!&lt;/p&gt;
&lt;div class="section" id="google-summer-of-code-mentorship"&gt;
&lt;h2&gt;Google Summer of Code mentorship&lt;/h2&gt;
&lt;p&gt;Speaking about mentoring, I’m going to get my hands dirty again and
mentor someone for Google Summer of Code (GSoC) for the Django
organization this year! 🥳&lt;/p&gt;
&lt;p&gt;It will be my first time to mentor for Google Summer of Code, I’m really
excited! I will be mentoring &lt;a class="reference external" href="https://www.linkedin.com/in/keha-chandrakar-342a1a285/"&gt;Keha
Chandrakar&lt;/a&gt;
with my amazing co-mentor and co-chair of the Website Working Group
&lt;a class="reference external" href="https://saptaks.website/"&gt;Saptak Sengupta&lt;/a&gt;✨&lt;/p&gt;
&lt;p&gt;The project is &lt;a class="reference external" href="https://summerofcode.withgoogle.com/programs/2026/projects/zCsh2gn8"&gt;Unified Dark Mode and UI Consistency for Django’s Issue
Tracker&lt;/a&gt;,
it would be a nice addition for the community.&lt;/p&gt;
&lt;p&gt;This project means a lot to me. I have previously contributed to the
addition of the dark mode in the Django website. It was my first major
contribution to Django! When you start your contribution journey for a
huge project like Django, it’s exciting and impressive! I did contribute
without any mentor but I definitely had help along the way since the
Django community is so welcoming and helpful. I learned a lot through
this contribution and now it’s used by so many people. Being Keha’s
mentor is a good way for me to give back and help someone else on a
topic I know pretty well!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="you-could-be-the-mentor"&gt;
&lt;h2&gt;You could be the mentor&lt;/h2&gt;
&lt;p&gt;I have been part of the &lt;a class="reference external" href="https://djangonaut.space"&gt;Djangonaut Space&lt;/a&gt;
organization, where we are recruiting people as mentors.
This organization and the Django organization are always looking for mentors.
If you have already contributed to an open source project related to the
Django ecosystem or are maintaining one and you are willing to take the
time to help someone in their contribution journey, consider mentoring
as an option to get new contributors to your project. Djangonaut Space
has multiple cohorts, &lt;a class="reference external" href="https://buttondown.com/djangonaut-space"&gt;sign up to the newsletter and mention your
interest in mentoring&lt;/a&gt;:
being a navigator (technical mentor) or a captain (community mentor).&lt;/p&gt;
&lt;p&gt;Who knows, this might be your new co-maintainer, your new teammate or
your new code reviewer? There are things we can definitely learn on our
own and some things you will only learn from someone else.&lt;/p&gt;
&lt;p&gt;That’s it for me!&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category><category term="django"></category></entry><entry><title>2025, year in review</title><link href="https://sarahabd.com/blog/2025-year-in-review" rel="alternate"></link><published>2026-02-12T10:00:00+01:00</published><updated>2026-02-12T10:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2026-02-12:/blog/2025-year-in-review</id><summary type="html">&lt;p class="first last"&gt;Hi there, it has been a while… First of all, I want to say happy new year to you, best wishes !!&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it has been a while as usual! Happy new year dear reader! I hope the best for you.&lt;/p&gt;
&lt;p&gt;My end of the 2025 year has been really tricky for me so I'm definitely late writing this post but it's
never too late for anything right?&lt;/p&gt;
&lt;p&gt;It's always when you write this kind of post that you realized how much you have accomplished,
especially on things you weren't expecting to do, so many things on this field.
And all the things you didn't managed to do but, new year, new possibilities!&lt;/p&gt;
&lt;p&gt;So here we go, Sarah's year in review! ✨&lt;/p&gt;
&lt;div class="section" id="tl-dr"&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;This year was awesome, I success to do things and I wouldn't have expected to do, and I am very grateful for
all the support I had this year, all the amazing friends I have, all the opportunities I had.&lt;/p&gt;
&lt;p&gt;This year was also a year of learning and growth for me. Huge personal challenges that has pushed me to change,
improve and be more confident in myself. Still a lot of work to do but I feel I'm on the right path.&lt;/p&gt;
&lt;p&gt;My highlights for the year have been:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Be Vice President of the Django Software Foundation (DSF)&lt;/li&gt;
&lt;li&gt;Meet the community all over the world&lt;/li&gt;
&lt;li&gt;Organized a devroom in FOSDEM&lt;/li&gt;
&lt;li&gt;Keynoting in few conferences&lt;/li&gt;
&lt;li&gt;First full solo travel trip&lt;/li&gt;
&lt;li&gt;See remote friends in real life&lt;/li&gt;
&lt;li&gt;retake drawing and creative skills&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="volunteering-and-community"&gt;
&lt;h2&gt;Volunteering and community&lt;/h2&gt;
&lt;p&gt;I attended and spoke at several conferences this year, which was a great experience for me. I did that not only to
share my knowledge, promote Django and the DSF but also to see the community everywhere in the world.&lt;/p&gt;
&lt;p&gt;As a DSF representative, it was important for me to be present and accessible in the community. It was also a good way
to connect with people locally and get their feedback on how the DSF can better support them and things we could improve.&lt;/p&gt;
&lt;p&gt;I have attended and/or spoken at:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;PyCon IT&lt;/li&gt;
&lt;li&gt;FOSDEM&lt;/li&gt;
&lt;li&gt;DjangoCon Europe&lt;/li&gt;
&lt;li&gt;DjangoCon Africa&lt;/li&gt;
&lt;li&gt;DjangoCongress JP (online)&lt;/li&gt;
&lt;li&gt;PyCon Africa (online)&lt;/li&gt;
&lt;li&gt;PyCon FR&lt;/li&gt;
&lt;li&gt;DjangoDay India&lt;/li&gt;
&lt;li&gt;PyLadiesCon (online)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some others conferences I would have liked to attend but couldn't make it this year due to time or budget constraints
but I was involved in some ways like EuroPython where I helped to get a community booth.&lt;/p&gt;
&lt;p&gt;I gave my first keynote at PyCon IT, which was a huge milestone for me.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="My keynoter badge for PyCon IT with some stickers, FastAPI stickers, PyCon IT stickers and Django pony sticker." src="../images/2025-year-in-review/keynoter-badge-pycon-it.jpg" /&gt;
&lt;p class="caption"&gt;My keynoter badge for PyCon IT with some stickers&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It was scary but also very rewarding.
Thank you so much the organizing team for trusting me with this opportunity!
My keynote was on &lt;a class="reference external" href="https://youtu.be/TCNv0MZrxoY"&gt;raising awareness on accessibility&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Related to accessibility, with some friends we organized the first &lt;a class="reference external" href="https://archive.fosdem.org/2025/schedule/track/inclusive-web/"&gt;Inclusive Web Devroom&lt;/a&gt;.
FOSDEM is a huge event in Europe and it was a great opportunity to bring more visibility to this important topic.&lt;/p&gt;
&lt;p&gt;Still involved in my favorite community space, &lt;a class="reference external" href="https://djangonaut.space/"&gt;Djangonaut Space&lt;/a&gt;, where I helped as much as I can, and I switched to an
advisor role this year due to my other commitments.&lt;/p&gt;
&lt;p&gt;And one of my commitments was being Vice President of the DSF, which was a huge honor for me.&lt;/p&gt;
&lt;p&gt;I tried my best to represent the community and help the DSF to achieve its mission.
It's always hard to do all the things you have planned, especially as a volunteer,
but I think we made some good progress this year.&lt;/p&gt;
&lt;p&gt;I'm taking this opportunity to thank all the amazing people in the DSF board
and all the volunteers who are doing an amazing job to support the community and the project.
Specially, I want to thank the former DSF president, Thibaud Colas, who has been an excellent leader and teammate 💚&lt;/p&gt;
&lt;p&gt;I hope to be able to continue to grow, improve and welcome people to the Django community and
met other friends from all over the world. I will do my best to continue the DSF Member of the Month initiative,
which is a great way to highlight the great people in our community and their contributions.&lt;/p&gt;
&lt;p&gt;I'm sure there will be more to come in 2026!&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="creative-and-personal-projects"&gt;
&lt;h2&gt;Creative and personal projects&lt;/h2&gt;
&lt;p&gt;This year I realized I completely abandoned all the creative work I used to do,
and I'm trying to get back into it because it's something I really enjoy and I'm a fairly creative person in general.&lt;/p&gt;
&lt;p&gt;I retook drawing and painting, I really enjoy it, it's a good way for me to relax and express myself.
I also want to try other creative things like photography, but I need to change my camera first,
so if you have any recommendation, let me know!&lt;/p&gt;
&lt;p&gt;I'm also trying to do some self-work, I think it's important to take care of yourself and work on your personal growth.
I have been reading some books on this topic and it's really helpful for me.
I want to keep doing this work and improve myself in many areas,
I think it's important to be a better version of yourself to be able to help others too.&lt;/p&gt;
&lt;p&gt;I hope to share some of my learnings and insights on this topic in the future, maybe in a blog post or something like that.&lt;/p&gt;
&lt;p&gt;I'm also trying to learn new things, I have a long list of things I want to learn but I need to prioritize them.&lt;/p&gt;
&lt;p&gt;Some of the things I want to learn in 2026 are:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Improve my drawing skills&lt;/li&gt;
&lt;li&gt;Learn more about web accessibility&lt;/li&gt;
&lt;li&gt;Learn more about self-care and personal growth&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class="section" id="travel-and-experiences"&gt;
&lt;h2&gt;Travel and experiences&lt;/h2&gt;
&lt;p&gt;This year I had the chance to travel a lot for conferences and personal trips.
I love so much to travel and discover new places, cultures, and meet new people.
It's always a great way for me to meet friends in real life too.&lt;/p&gt;
&lt;p&gt;I have been to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Belgium&lt;/li&gt;
&lt;li&gt;France&lt;/li&gt;
&lt;li&gt;Greece&lt;/li&gt;
&lt;li&gt;Germany&lt;/li&gt;
&lt;li&gt;Ireland&lt;/li&gt;
&lt;li&gt;Italy&lt;/li&gt;
&lt;li&gt;India&lt;/li&gt;
&lt;li&gt;Netherlands&lt;/li&gt;
&lt;li&gt;Poland&lt;/li&gt;
&lt;li&gt;Tanzania&lt;/li&gt;
&lt;li&gt;United Kingdom&lt;/li&gt;
&lt;li&gt;United States of America&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of those trips were for conferences, some were for work or for personal reasons, but all of them were great experiences for me.
I realized I have been to almost all the continents this year, which is something I didn't expect to do when I started the year.&lt;/p&gt;
&lt;p&gt;I also had the chance to do my first full solo travel trip, which was such an achievement for me!&lt;/p&gt;
&lt;p&gt;I went first in Berlin in Germany completely alone, which was a bit scary but also very rewarding.
Funily, I choose to go when there was a festival of lights I didn't know about,
so I had the chance to see the city in a different way and it was really beautiful.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Brandenburg Gate with blue lights for the Festival of lights in Berlin" src="../images/2025-year-in-review/festival-of-lights-berlin.jpg" /&gt;
&lt;p class="caption"&gt;Brandenburg Gate with blue lights for the Festival of lights in Berlin&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Then I went to India for DjangoDay India, which was also a lovely experience.
I had the chance to meet many people from the community and discover the country.
I stayed more days to visit other cities, from the north to the south, and it was really amazing.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Bengaluru palace in India" src="../images/2025-year-in-review/bengaluru-palace.jpg" /&gt;
&lt;p class="caption"&gt;Bengaluru palace in India&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I really want to go back to India, there is so much to see and discover there.
It's a country where you either love it or hate it, but for me,
it's a place that has a lot of charm and I really enjoy it.&lt;/p&gt;
&lt;p&gt;Outside of Asia, I want to do more trips in Africa in the future.
I discover Tanzania for the first time this year with DjangoCon Africa and it was amazing.
I have written a &lt;a class="reference external" href="/blog/djangocon-africa-2025"&gt;blog post about my experience at the conference&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I really enjoyed the culture, the people, and the nature there.
There are so many beautiful places to see and I want to discover more of them.&lt;/p&gt;
&lt;p&gt;Europe is also a great place to travel, there are so many beautiful cities and countries to discover.
Some pictures of my trips in Europe:&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Warsaw in December with Christmas lights" src="../images/2025-year-in-review/warsaw-december-lights.jpg" /&gt;
&lt;p class="caption"&gt;Warsaw in December with Christmas lights, Poland&lt;/p&gt;
&lt;/div&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="figure"&gt;
&lt;img alt="Road in the center of Bologna, Italy" src="../images/2025-year-in-review/road-in-bologna.jpg" /&gt;
&lt;p class="caption"&gt;Road in the center of Bologna, Italy&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I have been to Americas too, but more in the north to visit family, I want to discover more of the south in the future.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="The Capitol in Washington DC, USA" src="../images/2025-year-in-review/capitol-washington-dc.jpg" /&gt;
&lt;p class="caption"&gt;The Capitol in Washington DC, USA&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I also experienced some things that I didn't expect to experience, like the breakup of my very long relationship,
which was a really hard experience but I think it was also a good opportunity for me to grow and learn more about myself.&lt;/p&gt;
&lt;p&gt;One thing I learned from all those travels and experiences is that it's important to be open to new things and take time
to take care of yourself, especially when you are in a new place or going through a hard time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="lessons-and-insights"&gt;
&lt;h2&gt;Lessons and insights&lt;/h2&gt;
&lt;p&gt;I've learned a lot during the 2025's year, by trying things, going out of my comfort zone and making mistakes, of course.&lt;/p&gt;
&lt;p&gt;I tried to be more close to what I really want which means improving myself in many topics.
I improved my public speaking skills by giving talks in conferences.
I improved my leadership skills by being Vice President of the DSF and other volunteering roles.
I still have work to do but I'm proud of the progress I made.&lt;/p&gt;
&lt;p&gt;I keep working on my communication skills, especially in English, and I feel a bit more comfortable now.
I learned to think more about myself and my needs, still a work in progress but there are improvements.&lt;/p&gt;
&lt;p&gt;I also learned a lot by meeting people and chatting with them, I have the chance to meet many amazing people this year
and I'm really grateful for that.&lt;/p&gt;
&lt;p&gt;I know that I'm really good at connecting people to each other, which is something I really enjoy and I want to keep doing it.
I also learned that it's important to take care of yourself and work on your personal growth,
I think it's important to be a better version of yourself to be able to help others too.&lt;/p&gt;
&lt;p&gt;My favorite quote for this year was &amp;quot;Feel the fear and do it anyway&amp;quot; by Susan Jeffers,
which is a great reminder for me to keep trying new things and not be afraid of failure.&lt;/p&gt;
&lt;p&gt;My quote for 2026 is &amp;quot;Try more things, take more risks, embrace more discomfort&amp;quot; by Peter McKenzie,
which is a reminder for me to keep improving myself in many areas and be ok with the fact of not being comfortable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reminder-to-myself"&gt;
&lt;h2&gt;Reminder to myself&lt;/h2&gt;
&lt;p&gt;2025 I keep trying things I wasn't comfortable with. 2026, Tim Schilling recently asked me what would be my theme for this year,
I think it would be &amp;quot;letting go and self-love&amp;quot; as I want to keep improving myself in many areas.&lt;/p&gt;
&lt;p&gt;It's a long road but I'm confident. It will not be easy but I'm not alone and it can just help me to be a better version of
myself and be able to help others too.&lt;/p&gt;
&lt;p&gt;Piece of advice to tell for this new year:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Keep trying, making mistakes is not that bad&lt;/li&gt;
&lt;li&gt;Practice is important to be good at something&lt;/li&gt;
&lt;li&gt;Be kind to yourself&lt;/li&gt;
&lt;li&gt;Letting go of what doesn't serve you anymore&lt;/li&gt;
&lt;li&gt;Focus on what matters to you&lt;/li&gt;
&lt;li&gt;Celebrate your progress, no matter how small&lt;/li&gt;
&lt;li&gt;Take time for self-care and reflection&lt;/li&gt;
&lt;li&gt;Embrace change and be open to new opportunities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Do what makes you happy and fulfilled, and don't be afraid to change your path if it doesn't feel right anymore.&lt;/p&gt;
&lt;p&gt;I hope this year will be a good one for you, and I wish you all the best for 2026!&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category></entry><entry><title>DjangoCon Africa 2025</title><link href="https://sarahabd.com/blog/djangocon-africa-2025" rel="alternate"></link><published>2025-08-28T04:00:00+02:00</published><updated>2025-08-28T04:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2025-08-28:/blog/djangocon-africa-2025</id><summary type="html">&lt;p class="first last"&gt;Hi there, it’s have been a while… I have been for the first time to DjangoCon Africa few weeks ago. It was in Arusha, Tanzania.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it's been a while as usual. I have been for the first time to DjangoCon Africa few weeks ago. It was in Arusha, Tanzania.&lt;/p&gt;
&lt;p&gt;Tim Schilling has written an excellent blog post about his experience at DjangoCon Africa, you can read &lt;a class="reference external" href="https://www.better-simple.com/django/2025/08/25/djangocon-africa-2025-recap/"&gt;his blog post&lt;/a&gt;.
He collected the other abstracts from the conference participants.&lt;/p&gt;
&lt;div class="section" id="first-djangocon-africa"&gt;
&lt;h2&gt;First DjangoCon Africa&lt;/h2&gt;
&lt;p&gt;It's always a special feeling when it's your first time in a conference.
You meet new people, discover how the conference is run and familiarize yourself with the organization and how it is supposed to work.&lt;/p&gt;
&lt;p&gt;I know DjangoCon Europe well, I have been an organizer, a volunteer and an attendee.
One thing you have to know is DjangoCon events are run by volunteers for free.
I really would like to thank the organizers and volunteers behind this conference.
I know it's a lot of work behind the scenes, but gathering people in one place and seeing folks connecting and share knowledge it's a priceless joy.
If you want to help the community globally, this is a really good way to contribute.&lt;/p&gt;
&lt;p&gt;Moreover, I would like to thank all the sponsors that made this conference possible.
This is particularly important to me because the community must be represented as a whole across all continents and conference like this one is the best way to show that.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Thibaud Colas and I in front the wall of DjangoCon Africa UbuCon Africa with all sponsors logos. We are showing the name of the conference and both smiling." src="../images/me-thibaud-wall.jpg" /&gt;
&lt;p class="caption"&gt;Thibaud and I showing the DjangoCon Africa UbuCon Africa wall&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I am proud of this picture, Me and Thibaud Colas, Vice President and President, in front the wall of DjangoCon Africa UbuCon Africa with all sponsors logos.
Sponsoring is crucial for the success of such events and if you care about diversity and inclusion in tech, supporting events like DjangoCon Africa is a great way to make a difference.&lt;/p&gt;
&lt;p&gt;As a board member, I am glad to have been able to participate in almost all Django events organized around the world so far to be in direct contact with the community.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="arusha-tanzania"&gt;
&lt;h2&gt;Arusha, Tanzania&lt;/h2&gt;
&lt;p&gt;I have never been to South of Africa except the country I have roots, &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Comoro_Islands"&gt;Comoros Islands&lt;/a&gt;.
Go to DjangoCon Africa was a good way to discover that and learn about Tanzania.
I really enjoyed Arusha, it's a lovely city. It was a real change of landscape for me, coming from Paris.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Road with closed shops in multi-colored jails in Arusha, Tanzania" src="../images/road-with-shops.jpg" /&gt;
&lt;p class="caption"&gt;Road with shops in Arusha, Tanzania&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It's also a good opportunity to discover the local culture, food and wildlife.
I had the time to do a Safari to Ngorongoro Crater with my lovely friend &lt;a class="reference external" href="https://www.better-simple.com/"&gt;Tim Schilling&lt;/a&gt;, go to the markets and try the local food.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Tim Shilling and I in the Jeep during the safari" src="../images/safari-with-tim.jpg" /&gt;
&lt;p class="caption"&gt;Safari with Tim Schilling&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Also, you see the challenge people are facing there and doing their best to overcome them. Despite this, people are welcoming and friendly. Always trying to help.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="the-conference"&gt;
&lt;h2&gt;The conference&lt;/h2&gt;
&lt;p&gt;Since it's a new conference for me, I tried my best to talk with as many folks as possible.
I was amazed by all the folks that came to me to talk, just for chatting or thanks me for my keynote and/or get feedback for their projects.
Usually it's the reverse, I will go to folks to talk to them. If you were at DjangoCon Africa and didn't connect with me, you can still do it!&lt;/p&gt;
&lt;p&gt;Outside of the local community, this conference gave me the opportunity to met old friends and new friends.
Conferences are a great way to see your international friends and meet new folks from everywhere.
I know folks from all over the world, that's really cool no? 😁&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Group photo of everyone in DjangoCon Africa 2025" src="../images/group-photo.jpg" /&gt;
&lt;p class="caption"&gt;Everyone in front the wall before the end of the conference&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Something I love is to meet folks from &lt;a class="reference external" href="https://djangonaut.space/"&gt;Djangonaut Space&lt;/a&gt; in person in addition to the local community.
I was able to meet &lt;a class="reference external" href="https://www.linkedin.com/in/salim-abdella/"&gt;Salim Nuru&lt;/a&gt;, &lt;a class="reference external" href="https://www.philipnarteh.me/"&gt;Philip Nareth&lt;/a&gt; and Tim Schilling in person.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Five members of Djangonaut Space meeting up at DjangoCon Africa 2025, smiling and pointing to the sky!" src="../images/djcafrica-djangonauts.jpg" /&gt;
&lt;p class="caption"&gt;The Djangonaut Space crew at DjangoCon Africa 2025&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I'm sad &lt;a class="reference external" href="https://rahma.hashnode.dev/"&gt;Rahmat Akintola&lt;/a&gt; wasn't able to come, next time hopefully.&lt;/p&gt;
&lt;p&gt;Now I can say I have seen all the founders and co-founders of Djangonaut Space in person 🚀&lt;/p&gt;
&lt;p&gt;Tim is one of my very good friends, I was so happy to meet him in person and be able to support him for his keynote.
It's unbelievable that was the first time we met in person, after all the time we spent together on Djangonaut Space.
Remote relationships are real.&lt;/p&gt;
&lt;p&gt;I was glad to finally see folks who I have chatted with online occasionally like &lt;a class="reference external" href="https://www.linkedin.com/in/juliusboakye/"&gt;Julius Boakye&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="opening-keynote"&gt;
&lt;h2&gt;Opening Keynote&lt;/h2&gt;
&lt;p&gt;I was deeply honored to give the opening keynote of DjangoCon Africa: &amp;quot;50 shades of green - One contribution to the Django world&amp;quot;.
For those who are interested, you have the &lt;a class="reference external" href="https://sarahabd.com/shades"&gt;link of the slides&lt;/a&gt; . I will see to add the transcript later.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Me giving the opening keynote at DjangoCon Africa 2025" src="../images/me-keynoting.jpg" /&gt;
&lt;/div&gt;
&lt;p&gt;If my keynote has any impact on you, even years later, please tell me, I would like to hear your story!&lt;/p&gt;
&lt;p&gt;Unfortunately, talks were not recorded at this conference. I hope it will be the case next time, some content deserves to be shared beyond Africa.&lt;/p&gt;
&lt;p&gt;Each interaction has left a mark on my journey, and I look forward to continuing these conversations in the future.
I got some contacts for potential collaborations and projects, and I'm excited to see where these connections and projects will lead.&lt;/p&gt;
&lt;p&gt;As I mentioned in my keynote, I would like to encourage folks to contribute to Django and open source in general.
There are many ways to contribute, whether it's through code, documentation, internationalization or community support. Every little bit helps!
And even if it feels scary to start contributing, remember that everyone was a beginner at some point. Myself included.&lt;/p&gt;
&lt;p&gt;So don't be afraid to take that first step and get involved. The Django community is a friendly and welcoming place.&lt;/p&gt;
&lt;hr class="docutils" /&gt;
&lt;p&gt;This trip was especially meaningful for me. Despite navigating some personal challenges, the warmth and generosity of the community helped me set those worries aside.
My time at DjangoCon Africa was truly enriching, and I look forward to the possibility of returning in 2027.&lt;/p&gt;
&lt;p&gt;See you next time DjangoCon Africa! 💚&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category><category term="django"></category><category term="conferences"></category></entry><entry><title>DSF Vice President 2025</title><link href="https://sarahabd.com/blog/dsf-vice-president-2025" rel="alternate"></link><published>2025-02-20T12:00:00+01:00</published><updated>2025-02-20T12:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2025-02-20:/blog/dsf-vice-president-2025</id><summary type="html">&lt;p class="first last"&gt;Hi there, it has been a while since my last post, but I'm now back with a new role...&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it's been a while, as always 🙂
I had a though end of the 2024 year and beginning of 2025 (family loss) so I didn't do my usual year in review unfortunately, but I took the time to write my recent update: I'm the new Vice President of the Django Software Foundation 🎉&lt;/p&gt;
&lt;p&gt;This is such an honor to serve on the board of the Django Software Foundation, and it's even more the case as the Vice President. I'm particularly glad to have this role since it's a way to connect to our members and I already had lovely emails responses while onboarding new DSF members.&lt;/p&gt;
&lt;div class="section" id="vice-president-tasks"&gt;
&lt;h2&gt;Vice President tasks&lt;/h2&gt;
&lt;p&gt;The Vice President handle everything related to requests of new DSF members. Currently you can apply for yourself or apply for someone else. After that, it's reviewed and voted by the board for approval or not.&lt;/p&gt;
&lt;p&gt;If you planning to submit a DSF member, please add as many informations as you can, it's really helping us to know if the person meet the criterias to approuve the member.&lt;/p&gt;
&lt;p&gt;My tasks are:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;send emails to approved members&lt;/li&gt;
&lt;li&gt;add them to the mailing list used for the voting for the future boards and steering council&lt;/li&gt;
&lt;li&gt;add them to the private DSF member section in the forum&lt;/li&gt;
&lt;li&gt;attribute them the DSF role&lt;/li&gt;
&lt;li&gt;follow up for any specific inquiries related to current or onboarding members&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Besides that, I'm also the fallback of the President. If Thibaud is sick or can't do something related to his role, I will be the one to fill up the place. No fear, right? 😛&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://thib.me/president-of-the-django-software-foundation"&gt;As Thibaud was saying in his blog&lt;/a&gt;, there is some discovery to do to be able to fill the role as people and ourselves expected. I'm sure we will figure it out and document it 💪🏽
The President seems to be a role with many things to do and I will do my best to help him as much as I can.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="my-plans-for-2025-and-the-future"&gt;
&lt;h2&gt;My plans for 2025 and the future&lt;/h2&gt;
&lt;p&gt;I have been doing a lot of volunteering last year, one thing which is hard, is get a good balance to be able to do everything you wanted and take time for yourself. In function of your personality, it can be even harder to say no to a topic you care about just because you don't have enough time. That's why, my first plan is to improve processes and document things internally for the Vice President in case I decide to not continue to serve the board.&lt;/p&gt;
&lt;p&gt;This year I would like to automate partially or completely the process of onboarding a new DSF member to have less time gap in terms of announcement of members approval and the time they are actually onboarded and added. This will be also a way to allow the Vice President to spend time on other things too.&lt;/p&gt;
&lt;p&gt;I will continue my work related what I mentioned in my statement and will do my best to represent the Django Software Foundation and this nice framework and people behind it around the world 💚&lt;/p&gt;
&lt;p&gt;I will see to achieve things I haven't done as many actions as I wanted (Accessibility, Django website etc.) and support other board members and any folks who are happy to step in, in the Django governance and Django work that fulfill the DSF's mission.&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="django"></category><category term="dsf"></category><category term="reflexion"></category></entry><entry><title>TIL: python Protocol and typing</title><link href="https://sarahabd.com/til/python-protocol-typing" rel="alternate"></link><published>2024-12-18T14:00:00+01:00</published><updated>2024-12-18T14:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-12-18:/til/python-protocol-typing</id><summary type="html">&lt;p class="first last"&gt;Python Protocols, the simple explanation from me&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;I’m still learning a lot around Python, and I discovered Protocol some
months ago and I wanted to write that down to not forget.&lt;/p&gt;
&lt;p&gt;Protocol was created in Python 3.8 with the &lt;a class="reference external" href="https://www.notion.so/TIL-python-Protocol-and-typing-67e79fcf2547409cafb77a5594380008?pvs=21"&gt;PEP
544&lt;/a&gt;.
There a multiple protocols in python but the one I’m talking about is a
way to define structural typing. Some of you will also call that
implicit interface. We can use the &lt;tt class="docutils literal"&gt;Protocol&lt;/tt&gt; class from
the &lt;tt class="docutils literal"&gt;typing&lt;/tt&gt; module. To not confuse you even more, I will explain that
with a simple image.&lt;/p&gt;
&lt;p&gt;If we consider you as a journalist and you are writing tech articles,
week notes and many type of writing; you always have things you will do
for your posts despite the type of them, for example, such as:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;mark it as draft&lt;/li&gt;
&lt;li&gt;publish&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To make sure you not forget those things, let’s create a template, so
you don’t forget them. This template will be your protocol.&lt;/p&gt;
&lt;p&gt;With real code it should look like something like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;typing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Publishable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;That’s it, you can use it on any types of posts you want &lt;strong&gt;without
inheritating them&lt;/strong&gt;. This means that an object conforms to a protocol by
implementing the required methods. Here’s an example with the publish
method:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="c1"&gt;# do something to publish&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The class &lt;tt class="docutils literal"&gt;Article&lt;/tt&gt; is now implementing the protocol &lt;tt class="docutils literal"&gt;Publishable&lt;/tt&gt; with the addition of the required method &lt;tt class="docutils literal"&gt;publish&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;The pro and cons of that are:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pro&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;No need of inheritance pattern, less direct links and avoid drawbacks
of inheritance if you make changes&lt;/li&gt;
&lt;li&gt;Don’t forget to implement things and have more dynamics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Less readable, you have to know that&lt;/li&gt;
&lt;li&gt;Useful mostly for typing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I guess right now you’re thinking, great but how do I use this Protocol?
Good question!&lt;/p&gt;
&lt;p&gt;Protocols are primarily used for type hinting and static type checking.
This means you can use a protocol as a type annotation to indicate that
an argument or variable must conform to a specific protocol.&lt;/p&gt;
&lt;p&gt;If we retake our example, we will have this following code:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;publish_article&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Article&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;article&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In this case it’s only one Protocol used, but you could have multiple
Protocols used.&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Draft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;mark_as_draft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="c1"&gt;# do something to mark as draft&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="k"&gt;pass&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;DraftAndPublishable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Publishable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In this example, we define a protocol named &lt;tt class="docutils literal"&gt;Draft&lt;/tt&gt; with
a &lt;tt class="docutils literal"&gt;mark_as_draft&lt;/tt&gt; method. Then we define another protocol
named &lt;tt class="docutils literal"&gt;DraftAndPublishable&lt;/tt&gt; that combines both
the &lt;tt class="docutils literal"&gt;Draft&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;Publishable&lt;/tt&gt; protocols.&lt;/p&gt;
&lt;p&gt;If you are familiar with the special methods &lt;tt class="docutils literal"&gt;__iter__&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;__next__&lt;/tt&gt;, if you implement both, then your object will use the
Iterator protocol ✨ You can learn more on &lt;a class="reference external" href="https://realpython.com/python-iterators-iterables/#what-is-the-python-iterator-protocol"&gt;Real Python blog post
related to Iterator
Protocol&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To conclude with, Protocols provide a way to define structural typing in
Python, allowing you to create interfaces without the need for explicit
inheritance. They enable type checkers to verify that objects adhere to
the defined protocols, enhancing code correctness and maintainability.&lt;/p&gt;
&lt;p&gt;That’s it for now! I hope it will be useful for someone.&lt;/p&gt;
</content><category term="til"></category><category term="python"></category><category term="til"></category></entry><entry><title>DSF Board, AMA after 8 months</title><link href="https://sarahabd.com/blog/dsf-board-ama-after-8-months" rel="alternate"></link><published>2024-11-16T06:00:00+01:00</published><updated>2024-11-16T06:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-11-16:/blog/dsf-board-ama-after-8-months</id><summary type="html">&lt;p class="first last"&gt;My experience and all the questions folks have asked me about DSF Board&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it's been a while, I always have many ideas to write and no time,
but I try to find some to talk about the &lt;a class="reference external" href="https://www.djangoproject.com/foundation/"&gt;Django Software Foundation&lt;/a&gt; (DSF) board.
I might forget things to say so I might do a DSF blog series.
This time I decided to re-write this post and directly answer questions I was asked on social media or in person.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DISCLAIMER&lt;/strong&gt;: This is my personal opinion, I do not intend to blame anyone except myself.
This is my reflection from the past few months, including the fact I’m still learning about the board.&lt;/p&gt;
&lt;div class="section" id="how-did-you-become-a-dsf-board-member"&gt;
&lt;h2&gt;How did you become a DSF board member?&lt;/h2&gt;
&lt;p&gt;I was elected by &lt;a class="reference external" href="https://www.djangoproject.com/foundation/individual-members/"&gt;DSF members&lt;/a&gt;. If you want to learn more about DSF membership,
you can check the django website and if you think you or someone else are suitable, please apply.
I started to serve on the board from January 2024, and my term will end in December 2025.
Each board member have 2 term year and we have 4 specific officer roles:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;President&lt;/li&gt;
&lt;li&gt;Vice President&lt;/li&gt;
&lt;li&gt;Treasurer&lt;/li&gt;
&lt;li&gt;Secretary&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don’t have any specific role, I was planning to see how it’s going and then see what I can do.
And also, how it will go with my current tasks and (huge) to-do list.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="whats-different-from-your-expectations"&gt;
&lt;h2&gt;What’s different from your expectations?&lt;/h2&gt;
&lt;p&gt;I think coming back from &lt;a class="reference external" href="https://djangonaut.space/"&gt;Djangonaut Space&lt;/a&gt; organization I was expecting some similarities in terms of communication
and organisation but it wasn't the case. I was expecting more asynchronous communication and interaction since
we might all be busy for many reasons.&lt;/p&gt;
&lt;p&gt;A bit more defined things like who should answer emails and what about spams for example.&lt;/p&gt;
&lt;p&gt;1h of board meetings a month is not enough to me and some topics are not really discussed outside the meetings.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-do-you-think-needs-to-happen-in-the-future-to-set-the-board-and-the-dsf-up-for-long-term-success"&gt;
&lt;h2&gt;What do you think needs to happen in the future to set the board and the DSF up for long term success?&lt;/h2&gt;
&lt;p&gt;Put more effort in fundraising, I believe having more money will help to take actions in more domains.&lt;/p&gt;
&lt;p&gt;Also, have a better link with the community.
Sometimes we have issues where having feedback and support from the community would be helpful to address them.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-many-of-your-dsf-board-specific-initiatives-are-things-that-could-be-done-not-being-a-board-member"&gt;
&lt;h2&gt;How many of your DSF board specific initiatives are things that could be done NOT being a board member?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;For example, solving the problem of onboarding and nurturing new contributors is tackled by Djangonaut Space
on our own initiative. But approving grants and selecting a DjangoCon Europe team can only be done by board members.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So many things can be done without being a board member actually 😁&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Help people in the &lt;a class="reference external" href="https://forum.djangoproject.com/"&gt;Django forum&lt;/a&gt; or &lt;a class="reference external" href="https://discord.gg/xcRH6mN4fa"&gt;Django discord&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Moderate the forum and discord&lt;/li&gt;
&lt;li&gt;Initiate a &lt;a class="reference external" href="https://github.com/django/dsf-working-groups"&gt;working group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Participate to a working group&lt;/li&gt;
&lt;li&gt;Help with the content of the Django’s website&lt;/li&gt;
&lt;li&gt;Submit people as DSF members&lt;/li&gt;
&lt;li&gt;Create a local Django community (ie: Django Paris meetup)&lt;/li&gt;
&lt;li&gt;Search for community around the world to add to &lt;a class="reference external" href="https://www.djangoproject.com/community/local/"&gt;the local community page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Contribute to djangoproject.com / code.djangoproject.com website&lt;/li&gt;
&lt;li&gt;Contribute to the &lt;a class="reference external" href="https://github.com/django-discord/bot"&gt;Django Discord bot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Contribute to Django core to improve processes&lt;/li&gt;
&lt;li&gt;Contribute to a &lt;a class="reference external" href="https://www.djangoproject.com/foundation/teams/"&gt;Django team&lt;/a&gt; (ie: Triage and review team)&lt;/li&gt;
&lt;li&gt;Talk to people who could be part of a working group&lt;/li&gt;
&lt;li&gt;Volunteer in Django/DSF presence in events (ie: help run a Django booth)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="small-ways-to-get-involved-if-i-only-have-5-hours-per-month-i-can-contribute-where-do-you-need-people"&gt;
&lt;h2&gt;Small ways to get involved: If I only have 5 hours per month I can contribute, where do you need people?&lt;/h2&gt;
&lt;p&gt;They are many ways to contribute depends on the things you are more interested:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Immediate actions&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Help social media WG to provide content or review content&lt;/li&gt;
&lt;li&gt;Help Djangonauts on the forum or on discord, answer questions&lt;/li&gt;
&lt;li&gt;Retweet/retooth Django posts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Might need review / futures actions&lt;/strong&gt;&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Help on moderation (for example Reddit /r/django)&lt;/li&gt;
&lt;li&gt;DSF Fundraising WG might need extra help to reach potential sponsors&lt;/li&gt;
&lt;li&gt;If possible, come on the &lt;a class="reference external" href="https://www.djangoproject.com/weblog/2024/oct/16/announcing-weekly-dsf-office-hours/"&gt;DSF office hours&lt;/a&gt; to help answers or contribute to the conversation&lt;/li&gt;
&lt;li&gt;I would like at some point to have a content team for the website and help would be helpful here&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are interested in any of those actions please fill &lt;a class="reference external" href="https://framaforms.org/help-sarah-in-her-dsf-mission-1731706938"&gt;this form&lt;/a&gt;,
so I can reach you later if there are any specific needs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="if-and-how-the-dsf-is-setting-and-tracking-goals-for-diversity-and-inclusion"&gt;
&lt;h2&gt;If and how the DSF is setting and tracking goals for diversity and inclusion?&lt;/h2&gt;
&lt;p&gt;We have a &lt;a class="reference external" href="https://www.djangoproject.com/diversity/"&gt;public statement for diversity&lt;/a&gt; and some ongoing DEI improvements.&lt;/p&gt;
&lt;p&gt;Currently it’s more to define what is the existing state and the evolution with statistics to be able to set goals.&lt;/p&gt;
&lt;p&gt;The actions that had been taken is mostly to show how diverse the community is in the Django world, which means:
the website, elections, the members and Django communication tools:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The local community page&lt;/li&gt;
&lt;li&gt;Recognize DSF members from all over the world&lt;/li&gt;
&lt;li&gt;Small initiatives to help to get a good representation of the diversity of the community in DSF board elections&lt;/li&gt;
&lt;li&gt;Talk about the current DSF members&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Could be even more, having Django participate in the &lt;a class="reference external" href="https://www.outreachy.org/"&gt;Outreachy program&lt;/a&gt; and so on.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-are-the-tasks-and-time-commitments"&gt;
&lt;h2&gt;What are the tasks and time commitments?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Regular tasks as a baseline and then ad-hoc tasks/personal initiatives with rough times&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;We have a meeting each month and it lasts one hour. During this time, we are reviewing all current and new business
with all members and the assistant Catherine.&lt;/p&gt;
&lt;p&gt;Except that, we have async communication on slack.&lt;/p&gt;
&lt;p&gt;Since I don't have a specific role, it's mostly promotion and representation of the Django Software Foundation and
following DSF working groups as a board of liaison. We have a contact form so I have to check emails and reply if
I can.&lt;/p&gt;
&lt;p&gt;In more ad-hoc tasks/personal initiatives, I don’t know precisely the time but I think it depends on the task,
if it’s research on a topic or doing something for a working group. I’m involved in 3 working groups,
which means that there might be meetings or actions that I may have to do related to that.&lt;/p&gt;
&lt;p&gt;It’s hard to explicitly define times, but I think I could say around 5+ hours a month, depending on the need and
my health.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-areas-do-you-think-the-board-could-improve-on-and-where-does-it-lack-skills-expertise"&gt;
&lt;h2&gt;What areas do you think the board could improve on and where does it lack skills/expertise?&lt;/h2&gt;
&lt;p&gt;I think the board could improve in promotion: get sponsors, offer sponsorship package in function of the level
of sponsoring, get contacts…&lt;/p&gt;
&lt;p&gt;And I believe in terms of legal considerations and marketing we are lacking expertise.
For example Django is known from developers for its stability and smooth upgrades, this is something
which is not promoted, or at least poorly by saying it’s “boring”.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="any-behind-the-curtain-stuff-any-pain-points"&gt;
&lt;h2&gt;Any &amp;quot;behind the curtain&amp;quot; stuff? Any pain points?&lt;/h2&gt;
&lt;p&gt;Should I really share behind the curtain stuff? 😁&lt;/p&gt;
&lt;p&gt;I think the major pain point for me was communication and documentation.&lt;/p&gt;
&lt;p&gt;Many things are not documented or partially and with all different boards I imagine things have been lost over time.
It’s hard to understand everything when you are new.&lt;/p&gt;
&lt;p&gt;Also, I would have preferred to have the tasks shared or potentially allow/push people to ask for help if no time
or whatever reason, especially when they have a role which can ask a lot.
It took me a lot of time to figure out who writes our news pages.
Access and the processes to ask for access are not always clear to me.
This kind of thing should be documented somewhere.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-does-the-board-decide-things-do-you-vote-on-everything"&gt;
&lt;h2&gt;How does the board decide things (do you vote on everything)?&lt;/h2&gt;
&lt;p&gt;As I was saying before, we have a board meeting each month and we have a precise agenda that we are reviewing
together:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Grant submissions&lt;/li&gt;
&lt;li&gt;DjangoCon proposal&lt;/li&gt;
&lt;li&gt;DSF memberships&lt;/li&gt;
&lt;li&gt;DSF working group&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of those areas are voted on each time if there is anything to vote on,
so we are making sure that we have a quorum before the start of the meeting, otherwise it will be rescheduled.
We also discuss things related to the DSF organisation like bylaws, trademark etc.
but things aren’t always under vote except if there is a major change.
All board members can add a topic to the agenda.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-things-folks-should-involve-the-board-with-and-what-can-they-just-do"&gt;
&lt;h2&gt;What things folks should involve the board with and what can they &amp;quot;just do&amp;quot;.&lt;/h2&gt;
&lt;p&gt;Some &lt;a class="reference external" href="https://github.com/django/dsf-working-groups"&gt;DSF working groups&lt;/a&gt; already exist, all members are identifiable and the way to join the working group.&lt;/p&gt;
&lt;p&gt;Everyone can help a working group without asking a board member.&lt;/p&gt;
&lt;p&gt;Everyone can create a DSF working group, but this needs at least one board member to follow and guide the
working group (=board liaison) with the DSF board vision and for reporting. When the proposal is ready,
the board liaison will bring it to the board meeting to be voted on by the board.&lt;/p&gt;
&lt;p&gt;There are also initiatives like Djangonaut Space, &lt;a class="reference external" href="https://django-news.com/"&gt;Django News&lt;/a&gt; etc. which don’t rely on the board at all,
if you have an idea which might solve something in the Django community, please do it!&lt;/p&gt;
&lt;p&gt;The major thing which involves the board is creating a new DjangoCon since the name is registered under
the Django trademark with certain criterias. You can still create smaller events without the board,
and some of them are registered in &lt;a class="reference external" href="https://www.djangoproject.com/community/local/"&gt;the local community page&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="your-personal-reflections-is-this-a-joy-or-a-chore"&gt;
&lt;h2&gt;Your personal reflections - is this a joy or a chore?&lt;/h2&gt;
&lt;p&gt;Hard to say, I have experienced both.&lt;/p&gt;
&lt;p&gt;I was frustrated to not be able to help in some cases or see people complaining but I didn’t get the information
at the board level directly where it could make a difference. So I keep notes and try to make changes but sometimes
it’s even just a matter of time or actions, it doesn’t go like you wanted and you’re disappointed with the result.&lt;/p&gt;
&lt;p&gt;I also enjoy people thanking me for some actions I have done, see them amazed with the DSF membership recognition
or just see people I know from other spaces (Djangonaut Space, Discord…) taking part in Django community contributions
in some way, even if it doesn’t end as expected like elections, this is really nice to see all folks from all over the
world gather for one thing in common.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="where-are-you-at-with-your-goals-are-we-on-track-if-we-aren-t-what-resources-would-it-take-to-accomplish-them"&gt;
&lt;h2&gt;Where are you at with your goals? Are we on track? If we aren't, what resources would it take to accomplish them.&lt;/h2&gt;
&lt;p&gt;If we retake &lt;a class="reference external" href="https://www.djangoproject.com/weblog/2023/nov/13/2024-dsf-board-candidates/"&gt;my personal statement from the Django blog post&lt;/a&gt;,
this is the current state:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;span class="underline"&gt;Increase fundraising&lt;/span&gt;: &lt;strong&gt;in progress&lt;/strong&gt; with DSF Fundraising WG
        &lt;ul&gt;
            &lt;li&gt;&lt;span class="underline"&gt;improving communication&lt;/span&gt;: ideas was shared with DSF social media WG, missing coordination with DSF Fundraising WG when the team have everything ready for&lt;/li&gt;
            &lt;li&gt;&lt;span class="underline"&gt;highlighting sponsors&lt;/span&gt;: this will be reviewed with the future DSF Website WG with coordination of DSF Fundraising WG&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;span class="underline"&gt;Develop our community&lt;/span&gt;:  &lt;strong&gt;in progress&lt;/strong&gt; with many new DSF members and newcomers
        &lt;ul&gt;
            &lt;li&gt;&lt;span class="underline"&gt;specifically helping existing and new contributor&lt;/span&gt;: sharing the community and meeting people in other events.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;&lt;span class="underline"&gt;Working group for mentorship&lt;/span&gt;: &lt;strong&gt;Discussion initiated&lt;/strong&gt;, I’m involved in too many working groups, I have now a volunteer to lead this project ✨ She will need people and resources to help her, an issue will be open soon, keep an eye on that.&lt;/li&gt;
    &lt;li&gt;&lt;span class="underline"&gt;Push accessibility in the framework&lt;/span&gt;: &lt;strong&gt;in progress&lt;/strong&gt;, we have new members and many ideas and discussions on going. This also rely a lot on DSF Website WG which will be soon kickstarted.&lt;/li&gt;
    &lt;li&gt;&lt;span class="underline"&gt;Django's diversity and expand the community&lt;/span&gt;: &lt;strong&gt;in progress&lt;/strong&gt;, have a better representation in Django like candidate elections or people shown in the website.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;I believe we are on track but I can’t do that alone, especially for social media, we will need people to help us to promote and write content.&lt;/p&gt;
&lt;p&gt;There are also topics I would like to have more people involved in:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;DSF Code of Conduct WG&lt;/li&gt;
&lt;li&gt;Moderation of Discord and Forum&lt;/li&gt;
&lt;li&gt;Future team to write content of the website&lt;/li&gt;
&lt;li&gt;Get folks feedbacks in order to make improvements&lt;/li&gt;
&lt;li&gt;Get sponsors feedbacks&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="what-did-you-achieve"&gt;
&lt;h2&gt;What did you achieve?&lt;/h2&gt;
&lt;p&gt;I’m happy with what I have achieved, even though I was thinking I would have done more.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Represent DSF at some events (e.g. FOSDEM)&lt;/li&gt;
&lt;li&gt;Django booth at EuroPython&lt;/li&gt;
&lt;li&gt;DjangoCon Europe lightning talk&lt;/li&gt;
&lt;li&gt;DjangoCon Europe DSF panel&lt;/li&gt;
&lt;li&gt;Handle DSF roles on discord server&lt;/li&gt;
&lt;li&gt;Reply to some questions on discord, forum or email&lt;/li&gt;
&lt;li&gt;Help to quickstart the DSF Fundraising WG&lt;/li&gt;
&lt;li&gt;Add local communities in local communities page&lt;/li&gt;
&lt;li&gt;Follow-up on draft of the DSF Website WG&lt;/li&gt;
&lt;li&gt;Help on the review of DjangoCon proposal of next year&lt;/li&gt;
&lt;li&gt;Help the social media WG&lt;/li&gt;
&lt;li&gt;Research on the DSF past board and history&lt;/li&gt;
&lt;li&gt;Help on the next Django developer survey&lt;/li&gt;
&lt;li&gt;Submit many people for DSF membership&lt;/li&gt;
&lt;li&gt;Listing of potential requests that Djangonauts would like&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="what-would-you-like-to-achieve"&gt;
&lt;h2&gt;What would you like to achieve?&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Automate partially or completely the addition of new DSF Individual Members&lt;/li&gt;
&lt;li&gt;Improve fundraising to be able to take more actions&lt;/li&gt;
&lt;li&gt;Improve the website with the DSF Website WG&lt;/li&gt;
&lt;li&gt;Create a content website (WG?) team&lt;/li&gt;
&lt;li&gt;Create a mentorship / leadership WG&lt;/li&gt;
&lt;li&gt;Create a way to get feedback from the community&lt;/li&gt;
&lt;li&gt;Improve forms for futures elections&lt;/li&gt;
&lt;li&gt;Create a DSF members blog series&lt;/li&gt;
&lt;li&gt;Create some “did you know” social media post related to DSF&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="what-do-you-wish-the-community-knew-that-would-make-your-role-easier"&gt;
&lt;h2&gt;What do you wish the community knew that would make your role easier?&lt;/h2&gt;
&lt;p&gt;This is actually some time commitment if you want to do things outside of the monthly meeting.
Your work and extra activities take time and some days this is hard to work on open source.&lt;/p&gt;
&lt;p&gt;We need to increase funding but the best way to start is with you, dear lovely reader.
If you are working for a company, you should ask if they are sponsoring Django if they use it and tell them why they should do that.
If you don’t know what to tell for why, you can start by the fact it will help pay our Fellows,
the 2 incredible women who are maintaining the tool every day they are relying on and keep the security and improvements on it.&lt;/p&gt;
&lt;p&gt;Many things could be solved by having money, but not only. Sometimes what we are missing is people.
Having mentors, having people to answer questions, people who moderate platforms, people who contribute to code source.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-made-you-laugh"&gt;
&lt;h2&gt;What made you laugh?&lt;/h2&gt;
&lt;p&gt;My onboarding, it was definitely not what I expected, even if I didn’t expect so much to be honest.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="would-you-do-it-again"&gt;
&lt;h2&gt;Would you do it again?&lt;/h2&gt;
&lt;p&gt;I think yes, not because this is particularly fun, but more because some things can change only at some level,
and I think I can be helpful here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="if-you-had-impostor-syndrome-how-do-you-deal-with-it"&gt;
&lt;h2&gt;If you had impostor syndrome, how do you deal with it?&lt;/h2&gt;
&lt;p&gt;Impostor syndrome is, unfortunately, my best friend, always there I don’t know why lol&lt;/p&gt;
&lt;p&gt;I think it's a question of thinking about the best way, even if I'm not the most competent person,
I think I have something to contribute, and that's why I was elected.&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="dsf"></category><category term="django"></category></entry><entry><title>TIL: Accessibility resources #2</title><link href="https://sarahabd.com/til/accessibility-resources-second-edition" rel="alternate"></link><published>2024-05-23T00:00:00+02:00</published><updated>2024-05-23T00:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-05-23:/til/accessibility-resources-second-edition</id><summary type="html">&lt;p class="first last"&gt;Hi there, I decided to a second edition of accessibility resources.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;I decided to start a second edition of accessibility resources,
I have learned many things about accessibility and I want to share these resources with you.
I have made sections related on topic you might be more interested.&lt;/p&gt;
&lt;div class="section" id="courses"&gt;
&lt;h2&gt;Courses&lt;/h2&gt;
&lt;p&gt;These courses are interesting as an introduction to accessibility and to review certain concepts if you are already familiar with accessibility notions.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.edx.org/learn/web-accessibility/the-world-wide-web-consortium-w3c-introduction-to-web-accessibility"&gt;Edx course: Introduction to Web Accessibility&lt;/a&gt; - Free course&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://practical-accessibility.today/"&gt;Sara Soueidan course: Practical Accessibility&lt;/a&gt; - Paid course&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="books"&gt;
&lt;h2&gt;Books&lt;/h2&gt;
&lt;p&gt;I'm a big fan of ebooks, I have all of them in that format if it's a requirement for you.
I haven't read everything but it's on my todo-list if not finished.
I added some links for people who wants to learn more but you can find them in other platforms.&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://abookapart.com/products/accessibility-for-everyone"&gt;Accessibility for everyone&lt;/a&gt;, Laura Kalbag - A book A Part&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Maximum-Accessibility-Making-Usable-Everyone/dp/0201774224"&gt;Maximum Accessibility: Making Your Web Site More Usable for Everyone: Making Your Web Site More Usable for Everyone&lt;/a&gt;, Sharron Rush  - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Practical-Web-Inclusion-Accessibility-Comprehensive/dp/1484254511"&gt;Practical Web Inclusion and Accessibility: A Comprehensive Guide to Access Needs&lt;/a&gt;, Ashley Firth - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Web-Accessibility-Cookbook-Inclusive-Experiences/dp/1098145607"&gt;Web Accessibility Cookbook: Creating Inclusive Experiences&lt;/a&gt;, Manuel Matuzovic - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Beyond-Accessibility-Compliance-Generation-Inclusive/dp/1484279476"&gt;Beyond Accessibility Compliance: Building the Next Generation of Inclusive Products&lt;/a&gt;, Sukriti Chadha - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Fixing-Access-Annoyances-Phil-Mitchell/dp/059600852X"&gt;Fixing Access Annoyances&lt;/a&gt;, Phil Mitchell - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Web-Accessibility-Standards-Regulatory-Compliance/dp/1590596382"&gt;Web Accessibility: Web Standards and Regulatory Compliance&lt;/a&gt;, Jim Thatcher, Mark Urban, Bruce Lawson, Michael R. Burks, Richard Rutter, Andrew Kirkpatrick, Christian Heilmann, Shawn Lawton Henry, Bob Regan, Cynthia D. Waddell - Amazon&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.amazon.com/Ensuring-Digital-Accessibility-through-Process/dp/0128006463"&gt;Ensuring Digital Accessibility through Process and Policy&lt;/a&gt;, Jonathan Lazar, Daniel F. Goldstein, Anne Taylor - Amazon&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="colors-and-contrast"&gt;
&lt;h2&gt;Colors and contrast&lt;/h2&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.whocanuse.com/"&gt;Color checker whocanuse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://contrast-grid.eightshapes.com/"&gt;Contrast grid matrix from eightshapes.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://chrome.google.com/webstore/detail/colorblindly/floniaahmccleoclneebhhmnjgdfijgg"&gt;Colorblindly chrome extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many great accounts and resources shared via &lt;strong&gt;#a11y&lt;/strong&gt; or &lt;strong&gt;#accessibility&lt;/strong&gt;, worth to follow them in social medias.&lt;/p&gt;
&lt;p&gt;That’s it for now! I hope it will be useful for someone.&lt;/p&gt;
&lt;/div&gt;
</content><category term="til"></category><category term="til"></category><category term="accessibility"></category><category term="resources"></category></entry><entry><title>TIL: Git push force with lease</title><link href="https://sarahabd.com/til/git-push-force-with-lease" rel="alternate"></link><published>2024-05-22T11:00:00+02:00</published><updated>2024-05-22T11:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-05-22:/til/git-push-force-with-lease</id><summary type="html">&lt;p class="first last"&gt;Git push force with lease, my new friend.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;I'm used to rebase my PRs with a git rebase and force push, I discovered my new friend: &lt;cite&gt;git push --force-with-lease&lt;/cite&gt; thanks to my coworkers.&lt;/p&gt;
&lt;div class="section" id="git-rebase"&gt;
&lt;h2&gt;Git rebase?&lt;/h2&gt;
&lt;p&gt;Git rebase is helpful to rewrite history of the commits in a specific branch. You have the &lt;a class="reference external" href="https://git-scm.com/docs/git-push"&gt;full documentation of git push&lt;/a&gt;.
If you are new or not fully familiar to git, I quite like &lt;a class="reference external" href="https://learngitbranching.js.org/"&gt;this website&lt;/a&gt; in order to to learn git and practice at the same time.
You can rewrite the history of your commits and then force push.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="force-vs-force-with-lease"&gt;
&lt;h2&gt;&lt;cite&gt;--force&lt;/cite&gt; vs &lt;cite&gt;--force-with-lease&lt;/cite&gt;&lt;/h2&gt;
&lt;p&gt;The difference between &lt;cite&gt;--force&lt;/cite&gt; and &lt;cite&gt;--force-with-lease&lt;/cite&gt; is with &lt;cite&gt;--force-with-lease&lt;/cite&gt; will push only if you are not overwriting any work on
the remote branch if more commits were added to the remote branch. If is not the case, the push will be cancelled and you will get an error.&lt;/p&gt;
&lt;p&gt;&lt;cite&gt;--force&lt;/cite&gt; will overwrite any work in the remote branch, no matter if there are anything new in the branch. As you can see, &lt;cite&gt;--force-with-lease&lt;/cite&gt;
is a safer option if you don't want to overwrite someone elses work by force pushing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="bonus-force-if-includes"&gt;
&lt;h2&gt;Bonus: &lt;cite&gt;--force-if-includes&lt;/cite&gt;&lt;/h2&gt;
&lt;p&gt;I discovered today via Mastodon that &lt;a class="reference external" href="https://adamj.eu/"&gt;Adam Johnson&lt;/a&gt; has done a post related to this before this one, worth take a look, I also learned about
&lt;cite&gt;--force-if-includes&lt;/cite&gt; : &lt;a class="reference external" href="https://adamj.eu/tech/2023/10/31/git-force-push-safely/"&gt;you can learn more on his article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That’s it for now! I hope it will be useful for someone.&lt;/p&gt;
&lt;/div&gt;
</content><category term="til"></category><category term="til"></category><category term="git"></category></entry><entry><title>My Accessibility Review Checklist</title><link href="https://sarahabd.com/blog/my-accessibility-review-checklist" rel="alternate"></link><published>2024-03-27T10:00:00+01:00</published><updated>2024-03-27T10:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-03-27:/blog/my-accessibility-review-checklist</id><summary type="html">&lt;p class="first last"&gt;My accessibility review checklist and others checklists&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, some of you already know I have an interest in accessibility
and contribute to open source projects in this domain. I wanted to write
a checklist to remind myself of things to check when I’m reviewing a PR
to avoid forgetting elements. This is from my point of view and I’m
still learning a lot about accessibility. This might be useful if you
want to do so too. I will also link to other checklists because many
things already exist before I write this article and they are awesome.&lt;/p&gt;
&lt;p&gt;If you have doubts for anything, you can check in the documentation:&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.w3.org/WAI/standards-guidelines/wcag/"&gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt;&lt;/p&gt;
&lt;div class="section" id="tl-dr"&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Here you have the summary of the checklist to care about:&lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox1" class="form-control"&gt;&lt;input type="checkbox" id="checkbox1" name="checkbox1"&gt;1.Test with accessibility checker tools&lt;/label&gt; &lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox2" class="form-control"&gt;&lt;input type="checkbox" id="checkbox2" name="checkbox2"&gt;2.Use semantic HTML&lt;/label&gt; &lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox3" class="form-control"&gt;&lt;input type="checkbox" id="checkbox3" name="checkbox3"&gt;3.Use appropriate alternative text for all images/icons&lt;/label&gt; &lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox4" class="form-control"&gt;&lt;input type="checkbox" id="checkbox4" name="checkbox4"&gt;4.Ensure keyboard navigation is possible&lt;/label&gt; &lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox5" class="form-control"&gt;&lt;input type="checkbox" id="checkbox5" name="checkbox5"&gt;5.Ensure color contrast meets accessibility standards&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox6" class="form-control"&gt;&lt;input type="checkbox" id="checkbox6" name="checkbox6"&gt;6.Check for correct usage of ARIA attributes&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox7" class="form-control"&gt;&lt;input type="checkbox" id="checkbox7" name="checkbox7"&gt;7.Add landmarks&lt;/label&gt;&lt;/p&gt;
&lt;p&gt;&lt;label for="checkbox8" class="form-control"&gt;&lt;input type="checkbox" id="checkbox8" name="checkbox8"&gt;8.Test with screen readers&lt;/label&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div class="section" id="the-detailed-checklist"&gt;
&lt;h2&gt;The detailed checklist&lt;/h2&gt;
&lt;div class="section" id="accessibility-checker-tools"&gt;
&lt;h3&gt;Accessibility checker tools&lt;/h3&gt;
&lt;p&gt;Testing is the most important part. Even if you are not aware of
everything in accessibility, you will know what is wrong and what you
have actually done and start to improve somewhere.&lt;/p&gt;
&lt;p&gt;You have many tools which can allow you to test your code properly and
give you some hints on the rule and/or the code possible to change.&lt;/p&gt;
&lt;p&gt;There are many ways to test a website. First we have the accessibility
tool checker. You can have it via a browser extension, via the direct
website or run it as an integrated tool in your project.&lt;/p&gt;
&lt;p&gt;Don’t forget that you can also use the developer tool with some checks
related to accessibility. For example, you can force theme colors to see
the changes. Personally, I use the browser extension &lt;a class="reference external" href="https://accessibilityinsights.io/downloads/"&gt;Accessibility
Insights&lt;/a&gt;. It suits my
needs most of the time and it’s a very complete tool.&lt;/p&gt;
&lt;p&gt;To avoid reinventing the wheel, I suggest you learn more on how to
&lt;a class="reference external" href="https://a11y.coffee/start-testing/"&gt;start accessibility testing via the article done by
a11y.coffee&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you would like to automate some tests, this is also something
possible.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“57.38% of total Issues were detected during automated tests”&lt;/em&gt;
according to &lt;a class="reference external" href="https://www.deque.com/automated-accessibility-testing-coverage/"&gt;Deque, you can find more information on the
website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pa11y is a great tool to automate your accessibility testing, you have
the Pa11y CI which is built to run under continuous integration. You can
find &lt;a class="reference external" href="https://pa11y.org/tutorials/"&gt;many tutorials on Pa11y&lt;/a&gt; on their
website.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="html-markup"&gt;
&lt;h3&gt;HTML markup&lt;/h3&gt;
&lt;p&gt;This is something we don’t frequently think about but this does impact
the accessibility. Div and span are tags without semantic meaning and
this is really important. Semantic elements are recognized by browsers
but also by screen readers and other assistive technologies. I think I
can’t write better about how it is important than &lt;a class="reference external" href="https://accessibilitywise.info/semantic-code-why-meaning-is-important/essentials/"&gt;Semantic Code. Why
meaning is
important&lt;/a&gt;
from &lt;a class="reference external" href="http://accessibiltywise.info/"&gt;accessibiltywise.info&lt;/a&gt; from
Edward Haynes.&lt;/p&gt;
&lt;p&gt;For example, when describing an unordered list, instead of using this
code:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Coffee&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tea&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Water&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;You could use these specific html elements:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Coffee&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tea&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Water&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="alternative-text"&gt;
&lt;h3&gt;Alternative text&lt;/h3&gt;
&lt;p&gt;Images and icons are nice and aesthetic but it’s meaningless for people
with low or no vision.&lt;/p&gt;
&lt;p&gt;Many tools and websites integrate an alternative text to make sure
people who can’t see or have difficulties seeing the image, have at
least the description of the image. Most of the time it’s a small
description but it’s better than nothing.&lt;/p&gt;
&lt;p&gt;In the website, verify you have an attribute alt on each media,
especially images.&lt;/p&gt;
&lt;p&gt;For example, when adding the company photo in a page, you could do
something like this:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt;
   &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/path/to/img&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Photo of the Company Staff holding a flag&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;To use a real use case, I took a picture from my blog below, if the image
is not accessible or the link is simply broken, it will lead to this
result as you can see below:&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="image result when there is a alternative text and an image broken" src="../images/image-result-for-alternative-text.png" /&gt;
&lt;p class="caption"&gt;Image result when there is a alternative text and an image broken&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="section" id="labels"&gt;
&lt;h3&gt;Labels&lt;/h3&gt;
&lt;p&gt;Many times, people like to skip or remove labels. Design, or whatever
reason, you shouldn’t do that. Visible labels are helpful to know what
this element represents. This is really meaningful when you have a form,
for example. A real example is with the placeholder on credit card
field:&lt;/p&gt;
&lt;blockquote cite="https://twitter.com/SaraSoueidan/status/1577941158491201537"&gt;
   &lt;p&gt;Using placeholder without a label on the credit card field for
example has the screen reader say “kisses kisses kisses kisses” (cz the
placeholder is xxxx-xxxx-xxxx-xxxx) instead of “credit card number”&lt;/p&gt;
   &lt;footer&gt;—Sara Soueidan, &lt;cite&gt;Twitter&lt;/cite&gt;&lt;/footer&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a class="reference external" href="https://twitter.com/SaraSoueidan/status/1578346744550543360"&gt;The recording of the screen reader is available.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this case, best would be to add a label linked to the field with the
for attribute like this:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cardNumber&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Card Number&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;cardNumber&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;text&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;inputmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;numeric&amp;quot;&lt;/span&gt;
   &lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;[0-9]*&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It’s possible to add a hint if needed with a span tag. People should be
able to enter payment card numbers in whatever format is familiar to
them. This means to be able to have additional spaces, hyphens and
dashes and it’s still possible to validate the correct format of the
field.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="keyboard-navigation"&gt;
&lt;h3&gt;Keyboard Navigation&lt;/h3&gt;
&lt;p&gt;Navigating through a website can be hard if you don’t help readers,
especially when they use only a keyboard and/or a screen reader. This is
why you should use the correct HTML markup and think about the
navigation. The best way is to try to navigate like someone else will
do.&lt;/p&gt;
&lt;p&gt;You will also notice the importance of the focus indicator in this type
of navigation, to know which element you are currently focusing on. If
you have been one day removing the outline of elements with CSS without
defining a new indicator, please reconsider it after knowing this.&lt;/p&gt;
&lt;p&gt;These are the steps to navigate in a website:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;Go through your page with the tab key&lt;/li&gt;
&lt;li&gt;Make sure every interactive element can be reached.&lt;/li&gt;
&lt;li&gt;Make sure every interactive element can be used.&lt;/li&gt;
&lt;li&gt;Make sure the order is logical.&lt;/li&gt;
&lt;li&gt;Make sure the focus is visible, unobscured, and has enough contrast.&lt;/li&gt;
&lt;li&gt;Do the same in reverse with Shift + Tab&lt;/li&gt;
&lt;li&gt;Make sure there are no focus traps&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The navigation is supposed to be logical through elements, if you see
something wrong then you can see how to change. This part is easier to
do when you have feedbacks or ask other folks to make sure it’s correct.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="color-and-contrast"&gt;
&lt;h3&gt;Color and contrast&lt;/h3&gt;
&lt;p&gt;Color and contrast are something which impact a lot of users:
disabilities, comfort if looking by night, low vision and so on.This is
important because this is the first thing we see in addition to the
content. Low contrast makes things hard to distinguish and hard to read,
particularly for people with low visual acuity or color blindness.&lt;/p&gt;
&lt;p&gt;You have many ways to ensure the contrast is enough and everyone can
read. You have the devtools from your browser that will help you check
directly on elements that have a color and/or background.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Color contrast with chrome devtools on djangoproject.com" src="../images/devtools-chrome-contrast.png" /&gt;
&lt;p class="caption"&gt;Color contrast of a text in the sidebar with chrome devtools on djangoproject.com&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can have an extension that you can add to your browser to also check
colors and contrast. For example, I personally use
&lt;a class="reference external" href="https://chrome.google.com/webstore/detail/colorblindly/floniaahmccleoclneebhhmnjgdfijgg"&gt;colorblindly&lt;/a&gt;
for Chrome to see the difference between colors visions that could
exist.&lt;/p&gt;
&lt;p&gt;Finally, you have dedicated websites or tools that will help you to
check contrast only for specific things. I really like &lt;a class="reference external" href="https://www.whocanuse.com/"&gt;whocanuse.com&lt;/a&gt;
about different types of vision between a color and the background color
associated.&lt;/p&gt;
&lt;p&gt;If you want to compare two colors with a matrix, &lt;a class="reference external" href="https://contrast-grid.eightshapes.com/"&gt;contrast-grid from
eightshapes.com&lt;/a&gt; is my go to.&lt;/p&gt;
&lt;p&gt;There are specific tools that help you to adapt the color in function of
the image for example. You can see that in social media, for example in
Instagram, the text over a background will be white or black in function
of the color, to make sure it has the correct contrast.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="aria-attributes"&gt;
&lt;h3&gt;ARIA attributes&lt;/h3&gt;
&lt;p&gt;ARIA is the abbreviation of Accessible Rich Internet Applications. This
is useful to provide accessible information in addition to the HTML
semantic, but this should be used only when it’s necessary.&lt;/p&gt;
&lt;p&gt;For example, something that should be used for showing the current
element: page, section... A good example is the breadcrumbs:&lt;/p&gt;
&lt;pre class="code html literal-block"&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;breadcrumbs&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blog&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/blog/accessibility&amp;quot;&lt;/span&gt;
            &lt;span class="na"&gt;aria-current&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;page&amp;quot;&lt;/span&gt;
         &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Accessibility
         &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ol&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The risk with ARIA is that people think each time it’s needed to add an
attribute and it’s not the case. HTML semantics can be sufficient in
some cases. For example, a tag button doesn’t need to have a role, it
automatically has a role button. You can find more information on ARIA
roles on the &lt;a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles"&gt;MDN
website&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="landmarks"&gt;
&lt;h3&gt;Landmarks&lt;/h3&gt;
&lt;p&gt;Landmarks are the “sections” that structure the website: header, main,
footer, nav…&lt;/p&gt;
&lt;p&gt;This can be defined via the HTML tags, main have its own tag and this
allows to define the main content of the page.&lt;/p&gt;
&lt;p&gt;Landmarks are especially useful to structure the page but also to move
from a section to another easily with screen readers.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="landmarks on djangoproject.com website" src="../images/landmarks.png" /&gt;
&lt;p class="caption"&gt;Landmarks displayed with squares on djangoproject.com with Accessibility Insights*&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;One thing to not forget is for a given type of landmark is used multiple
times, for example &lt;cite&gt;&amp;lt;nav&amp;gt;&lt;/cite&gt; for the navigation landmark, then each occurrence
needs a &lt;cite&gt;aria-label&lt;/cite&gt; to tell them apart.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="screen-readers"&gt;
&lt;h3&gt;Screen readers&lt;/h3&gt;
&lt;p&gt;Screen readers are very useful for people who have disabilities or
prefer to use them to make their life easier. Many would think it’s only
for blind people but it’s not the case. Someone with dyslexia can use a
screen reader when using a computer or someone who has motricity issues,
even temporary for example. Screen reader will announce the content of a
website via text-to-speech or on a braille display. They also propose multiple
ways to interact with the website with a keyboard, it's not only reading
content: fill a form, interact with the browser and so on.&lt;/p&gt;
&lt;p&gt;There are different screen readers in function of the device or browser
supported and functionalities. JAWS and NVDA are the most popular.
VoiceOver is the one by default on Apple devices. Microsoft operating
systems use Microsoft Narrator. Android based devices provide Talkback
screen reader or VoiceView by default. For Linux and Unix systems you
have Orca or SpeakUp. You should be able to have a screen reader for
your device.&lt;/p&gt;
&lt;p&gt;You just need to try to put yourself in someone else’s shoes who can’t
perfectly see the website and walk through the website with the tool.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conclusion"&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;To summarize, this accessibility review checklist is a good way to
introduce people to accessibility and review your own sites to correct errors
that might force people not to use your site. This one is my own
checklist but there are many nice checklists, you can give a look
at the list below.&lt;/p&gt;
&lt;p&gt;Special thanks to the reviewers of this article, who should recognize themselves.
Thank you for your support 💚&lt;/p&gt;
&lt;p&gt;-- May the future be accessible with those checklists ⭐&lt;/p&gt;
&lt;div class="section" id="other-checklists"&gt;
&lt;h4&gt;Other checklists&lt;/h4&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.magentaa11y.com/"&gt;https://www.magentaa11y.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://www.a11yproject.com/checklist/"&gt;https://www.a11yproject.com/checklist/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://webaim.org/standards/wcag/checklist"&gt;https://webaim.org/standards/wcag/checklist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://webflow.com/accessibility/checklist#start"&gt;https://webflow.com/accessibility/checklist#start&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://dequeuniversity.com/checklists/web/"&gt;https://dequeuniversity.com/checklists/web/&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="accessibility"></category><category term="resources"></category></entry><entry><title>FOSDEM 2024, from my perspective</title><link href="https://sarahabd.com/blog/fosdem-2024-from-my-perspective" rel="alternate"></link><published>2024-02-15T10:00:00+01:00</published><updated>2024-02-15T10:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-02-15:/blog/fosdem-2024-from-my-perspective</id><summary type="html">&lt;p class="first last"&gt;First time for me to got to FOSDEM, my thoughts of the conference.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it’s been a while! I hadn’t time to take care of my blog these
days but I have so many ideas to write about! I will start with the
FOSDEM conference 🙂&lt;/p&gt;
&lt;p&gt;It’s my first time to this conference, FOSDEM is a 2 days conference
about free open source software, the conference is also free, run by
volunteers, same as open source. It takes place in Brussels, Belgium
this year. You can learn more on the
&lt;a class="reference external" href="https://fosdem.org/2024/"&gt;FOSDEM website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have been there with the Django Accessibility Team and with some
friends from the Wagtail team. It’s always more fun when you do a
conference with friends!&lt;/p&gt;
&lt;p&gt;Personally, I liked the conference, I guess there might be also the hype
of the first time conference here. Compared to other conference I have
been, you have many tracks (also called Devroom) so it can be hard to find
your way at the beginning but you finally manage your way (or follow some
people who are going to the same talk).&lt;/p&gt;
&lt;p&gt;I have seen few accessibility talks and some I wanted to see out of
curiosity. I also support my friend &lt;a class="reference external" href="https://fosdem.org/2024/schedule/speaker/DVT93T/"&gt;Sage Abdullah&lt;/a&gt; who was giving a talk
too ❤️&lt;/p&gt;
&lt;p&gt;The talks I have been to:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-2522-outreachy-1000-interns/"&gt;Keynote, Outreachy, 1000 interns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-3317-web-accessibility-and-environmental-sustainability-and-with-popular-cms/"&gt;Web Accessibility and Environmental Sustainability and with Popular
CMS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-3326-web-accessibility-for-open-source-privacy-security-tools/"&gt;Web-accessibility for open-source privacy &amp;amp; security tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-2723-power-profiling-my-entire-house-with-the-firefox-profiler/"&gt;Power profiling my entire house with the Firefox Profiler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-2716-firefox-power-profiling-a-powerful-visualization-of-web-sustainability/"&gt;Firefox power profiling: a powerful visualization of web
sustainability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-2749-modern-editing-experiences-you-can-build-in-your-cms/"&gt;Modern editing experiences you can build in your CMS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s also quite funny, I have done mostly conferences in full english
and since I’m french, I wasn’t sure each time if I should speak french
or english, and sometimes I discovered after talking in english to
someone, this person was actually speaking french to someone else
hahaha.&lt;/p&gt;
&lt;p&gt;The talks I wanted to see was mostly on Sunday so I talked a lot to
people in Saturday and discovering the various stands there were. It was
really diverse, Mastodon, Mozilla, Postgresql, Open design collective,
OpenSSL, Debian, even XMPP!&lt;/p&gt;
&lt;p&gt;I made new friends, of course, see old friends, and see some people I
know their name but never see them in real so it’s quite nice.&lt;/p&gt;
&lt;p&gt;The thing I really like was the BoF, which mean Both of Feather, it
happens most of the time after a specific talk, and it’s a good
opportunity to discuss with people from a talk or just people involved
in a specific track (for example python or accessibility).&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;BoF - &lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-3700-outreachy-connect-newcomers-old-friends/"&gt;Outreachy Connect: Newcomers &amp;amp; Old friends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;BoF - &lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-3757-web-accessibility-and-atag/"&gt;Web Accessibility and ATAG&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have been to the Outreachy one and another one on accessibility. It
was really interesting to talk with people, ask questions and learn some
resources from other people. I would love to see happening the resource
about the WCAG for backend developers we were talking about in
accessibility BoF and have a dedicated track for accessibility.&lt;/p&gt;
&lt;p&gt;As the DSF board member, the Outreachy program seems to be interesting to
have for Django at some point. I also find disturbing to see so many
people no knowing Django at all, I think it would be nice to have
something representing Django next year. Nevertheless, we did find some people using
Django or knowing Django and found amazing to see the full accessibility
team at the event. We were thanks for our work on accessibility, this is
so priceless to have feedback on that and we love that.&lt;/p&gt;
&lt;p&gt;Sage represent CMS with python with his talk, and a lot of people in the
room was only doing PHP, so it was nice to see the appreciation of other
people of the work done in another language for quite same purpose in
content management system.&lt;/p&gt;
&lt;p&gt;Unfortunately, I didn't have time to see &lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-2311-making-python-safer-than-ever/"&gt;Cheuk's talk&lt;/a&gt; or talk from the Python Devroom
but I'm glad I saw her at least.&lt;/p&gt;
&lt;p&gt;Some of them were totally full, especially when it's a talk given by
Daniel Stenberg or Scott Chacon but I enjoyed watch them online:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.youtube.com/watch?v=aolI_Rz0ZqY"&gt;So you think you know Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://fosdem.org/2024/schedule/event/fosdem-2024-1931-you-too-could-have-made-curl-/"&gt;You too could have made curl!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I plan to be there next year, and I hope to see you there or have
your support from wherever you are!&lt;/p&gt;
</content><category term="blog"></category><category term="reflexion"></category><category term="open-source"></category></entry><entry><title>2023, year in review</title><link href="https://sarahabd.com/blog/2023-year-in-review" rel="alternate"></link><published>2024-01-04T10:00:00+01:00</published><updated>2024-01-04T10:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2024-01-04:/blog/2023-year-in-review</id><summary type="html">&lt;p class="first last"&gt;Hi there, it’s have been a while… First of all, I want to say happy new year to you, best wishes !!&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it’s have been a while… First of all, I want to say happy new year to you, best wishes !!&lt;/p&gt;
&lt;p&gt;I took the time to do a review of the year with the same model as I've done in 2021.
I was sick for the end of the year so I didn't finish my article before the end of 2023 but,
it's finished to be published today! 🎉&lt;/p&gt;
&lt;div class="section" id="disclaimer"&gt;
&lt;h2&gt;Disclaimer&lt;/h2&gt;
&lt;p&gt;I didn't review my article by someone else and I'm not a native English speaker, if there are mistakes, feel free to contact me and I will edit the article.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="tl-dr"&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;This year was incredible, I success to do things I can’t imagine do. I am very thankful for all the support I had this year, all the new amazing friends I have, all the opportunities I had.&lt;/p&gt;
&lt;p&gt;My highlights for the year have been:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Helps organizing the DjangoCon Europe&lt;/li&gt;
&lt;li&gt;All about Djangonaut Space program&lt;/li&gt;
&lt;li&gt;Do my first talk&lt;/li&gt;
&lt;li&gt;Change job&lt;/li&gt;
&lt;li&gt;Make friends all over the world&lt;/li&gt;
&lt;li&gt;Be elected for the DSF Board&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="learning-and-improvements"&gt;
&lt;h2&gt;Learning and improvements&lt;/h2&gt;
&lt;p&gt;I've learned a lot this year, by trying things, especially things I was really afraid of, and making mistakes of course.
I think this year was a year of change for me.&lt;/p&gt;
&lt;p&gt;I tried to be more close to what I really want. I changed job to a job where I do the technology
I like the most with an impact on climate change.&lt;/p&gt;
&lt;p&gt;I also learned by chatting with friends. I'm still not completely proud of my English level despite many people would say
it's really fine but I guess it’s just a matter of being comfortable to say the correct words for the meaning I want.&lt;/p&gt;
&lt;p&gt;I also met many people, I’m thankful they are all kind and lovely, thanks to the amazing Django community 💚
I’m very proud of the team of Djangonaut Space, we achieve something really nice and we have built a great relationship together.
I realized by that I’m really good at connecting people to each other.&lt;/p&gt;
&lt;p&gt;I hope to be able to continue to grow, improve and welcome people to the Django community and met other friends from all over
the world.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conferences"&gt;
&lt;h2&gt;Conferences&lt;/h2&gt;
&lt;p&gt;I've organized the DjangoCon Europe this year, it was a great experience for me. &lt;a class="reference external" href="/blog/djangocon-europe-2023-from-attendee-to-organizer"&gt;I wrote on this&lt;/a&gt;, and I’m really excited to the
next edition in Vigo! I think this time I will only attend to be able to see more my friends and exchange with people,
especially as I’m part of the DSF board, get feedback and build the future.&lt;/p&gt;
&lt;p&gt;I've also attended to DjangoCon US, it was very nice but I didn’t attend so long due to timezone. I hope to be able to attend in 2024,
I might have a chance to come 🤞🏽&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="djangonaut-space"&gt;
&lt;h2&gt;Djangonaut Space&lt;/h2&gt;
&lt;p&gt;If someone would have told me that I would co-create this project and
&lt;a class="reference external" href="https://www.djangoproject.com/weblog/2023/dec/08/2023-malcolm-tredinnick-memorial-prize-awarded-to/"&gt;we will get the Malcolm Tredinnick Award&lt;/a&gt;
for that I wouldn't trust this person hahaha.&lt;/p&gt;
&lt;p&gt;I'm really happy for we have achieved and the team we create. Now, I consider all of them as my friends and the thing which
is amazing is when we saw each other in real life, it's like we know us like we are friends since years but this is the first
time we are seeing each other not in front of the computer.&lt;/p&gt;
&lt;p&gt;We are really trying our best to make &lt;a class="reference external" href="https://djangonaut.space/"&gt;Djangonaut Space&lt;/a&gt; a good project. I hope this project will help a lot of Djangonauts to
contribute and skyrocket their contributions 🚀&lt;/p&gt;
&lt;p&gt;The funny thing is sometimes I think I should follow our program for myself hahaha. I really would like to improve my skills
in 2024.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="professional-career"&gt;
&lt;h2&gt;Professional career&lt;/h2&gt;
&lt;p&gt;Talking about improving my skills, I changed job to challenge myself and not staying in my comfort zone.
This is clearly not easy and I have the impostor syndrome that's hard to get rid of, but I keep going and trying to improve  and be not too hard with myself.&lt;/p&gt;
&lt;p&gt;Despite that, I’m happy I have changed job, I have discovered a lot and still learning. I have also learned about myself
with those experiences, for example, I think I’m good at help push something forward.&lt;/p&gt;
&lt;p&gt;I’m also really thankful of all the open source work and opportunities I have been given. I know that this has an impact
in the community but also in my career. There is the feeling like some people have, not doing enough - yeah I know,
this can be weird as someone who already doing a lot of things - and want to do more but I’m trying to keep a good balance
with volunteering and rest. If you have the same feeling, don't forget that, time for yourself is important too.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="talk-and-volunteering"&gt;
&lt;h2&gt;Talk and volunteering&lt;/h2&gt;
&lt;p&gt;I guess this is my best year for volunteering. I've volunteered for 2 DjangoCons, I help on Djangonaut Space organization,
contribute and maintain Django code and accessibility, and organize Django Paris meetup. I wouldn't have imagined doing
all this at the start of the year, but I think I have a strong appetite for doing things when nobody else wants to do them
- am I weird?&lt;/p&gt;
&lt;p&gt;Anyway, I’m really proud to have contribute to all of this work, the result is great and I’ve learned a lot with
these experiences. I made new friends and enjoyed seeing old friends. I'll do my best to keep working on all these issues.&lt;/p&gt;
&lt;p&gt;Moreover, I have given a &lt;a class="reference external" href="https://youtu.be/15ITa9E2dEs?si=57piJJ5PY8Es7MIO"&gt;talk for PyLadiesCon about how to create a mentorship program&lt;/a&gt;. If you know me, you already know that
I’m really not confident talking in public, even less if it’s in English. A wise friend told me you have to practice to
be more comfortable - Thank you Tim Schilling. So I’m trying even if I still find that scary hahaha. If you are thinking
to do that one day, just try. Maybe you will discover you are an amazing speaker 😄&lt;/p&gt;
&lt;p&gt;As I was saying before, I've tried many things this year, including run for the DSF board. This is something I really didn't
planned to do to be honest. Many friends have helped me to consider it and why I should do it. Thank you if you helped me in
my decision and/or if you have voted for this election. There were amazing candidates and I'm very honored to be
one of the DSF's representative on the board of directors. I'm still figuring out how it works and how to help correctly.
I'm thinking of doing blog posts on this at some point to share with you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="friends-and-support"&gt;
&lt;h2&gt;Friends and support&lt;/h2&gt;
&lt;p&gt;I have met so many people this year, I'm really thankful to had the opportunities to see some of them in real life
during conferences or meetups. The thing I like the most in tech community is the friends that you have virtually are real
friendships. I have the chance to have friends all over the world with my experiences. I had support from some of them,
I also gave support to others. Have fun virtually or in real life in some place.
This is really nice and I love the community for that.
Thank you if you have contribute to my success or support me in my failure,
I hope to have learned all the lesson to do better in 2024.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reminder-to-myself"&gt;
&lt;h2&gt;Reminder to myself&lt;/h2&gt;
&lt;p&gt;2023 I tried things I didn’t think I would have done. I have many goals in mind and big to-do list for 2024 but I'm confident,
I'm sure I will not able to do everything but it's listed somewhere to make progress in it.
I think this new year will be a good one and I hope the best for you if you are still reading this.&lt;/p&gt;
&lt;p&gt;Piece of advice to tell for this new year:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Keep being organized&lt;/li&gt;
&lt;li&gt;Keep trying, making mistakes is not that bad&lt;/li&gt;
&lt;li&gt;Practice is important to be good at something&lt;/li&gt;
&lt;li&gt;Something that you might think it’s stupid might be helpful for someone else&lt;/li&gt;
&lt;li&gt;Don’t be afraid to ask&lt;/li&gt;
&lt;li&gt;Keep your goals in mind and the rest too&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category></entry><entry><title>TIL: Django constraints</title><link href="https://sarahabd.com/til/django-constraints" rel="alternate"></link><published>2023-08-12T10:00:00+02:00</published><updated>2023-08-12T10:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2023-08-12:/til/django-constraints</id><summary type="html">&lt;p class="first last"&gt;I have done some work with constraints recently and I wanted to write something on it just to remind myself.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;I have done some work with constraint recently and I wanted to write
something on it just to remind myself. I hope it’s useful to you too.&lt;/p&gt;
&lt;p&gt;Database constraints are really useful to make sure each row is valid
before to save it. You have two type of constraints you can use just
before to record a new line in a table in Django: &lt;tt class="docutils literal"&gt;CheckConstraint&lt;/tt&gt;
and &lt;tt class="docutils literal"&gt;UniqueConstraint&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;I use PostgreSQL which has powerful tools, you can set database
constraint according what is implemented by Django.&lt;/p&gt;
&lt;p&gt;Explanations are always better with an example so here is a constraint
to avoid date overlapping between the start date and the end date:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;start_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;end_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;constraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CheckConstraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start_at__lt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;end_at&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'start_at_before_end_at'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UniqueConstraint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'unique_event_dates'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;CheckConstraint&lt;/tt&gt; ensures that the &lt;tt class="docutils literal"&gt;start_at&lt;/tt&gt; is before the
&lt;tt class="docutils literal"&gt;end_at&lt;/tt&gt;. The &lt;tt class="docutils literal"&gt;UniqueConstraint&lt;/tt&gt; ensures that there are no two
events with the same &lt;tt class="docutils literal"&gt;start_date&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;end_date&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;I discovered that if you want to make a &lt;tt class="docutils literal"&gt;UniqueConstraint&lt;/tt&gt; in Django,
it considers &lt;tt class="docutils literal"&gt;NULL&lt;/tt&gt; values as distinct, which I didn’t want in my
case.&lt;/p&gt;
&lt;p&gt;Going back to my previous example, here we have 2 records:&lt;/p&gt;
&lt;table border="1" class="docutils"&gt;
&lt;colgroup&gt;
&lt;col width="9%" /&gt;
&lt;col width="45%" /&gt;
&lt;col width="45%" /&gt;
&lt;/colgroup&gt;
&lt;thead valign="bottom"&gt;
&lt;tr&gt;&lt;th class="head"&gt;id&lt;/th&gt;
&lt;th class="head"&gt;start_date&lt;/th&gt;
&lt;th class="head"&gt;end_date&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody valign="top"&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;2019-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;2019-12-31&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both have the same &lt;tt class="docutils literal"&gt;end_date&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;start_date&lt;/tt&gt; set to &lt;tt class="docutils literal"&gt;NULL&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;These two records will be considered unique because a NULL is not equal
to another &lt;tt class="docutils literal"&gt;NULL&lt;/tt&gt; in SQL, so the two records are considered distinct.&lt;/p&gt;
&lt;p&gt;You can use &lt;tt class="docutils literal"&gt;WITH DISTINCT NULL VALUES&lt;/tt&gt; with PostgreSQL 15 but in my
case I was using an older version, of course,&amp;nbsp; so I needed to use
another option.&lt;/p&gt;
&lt;p&gt;If you want to make sure that &lt;tt class="docutils literal"&gt;NULL&lt;/tt&gt; values are not considered
distinct in the &lt;tt class="docutils literal"&gt;UniqueConstraint&lt;/tt&gt;, you can use the hash function with
the unique=True attribute instead.&lt;/p&gt;
&lt;p&gt;Here is an example of the hash function with the unique value based on
the previous code with the Event class. A &lt;tt class="docutils literal"&gt;sha256_hash&lt;/tt&gt; field which
combines all the fields I want in an hash:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;hashlib&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;start_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;end_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;fancy_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;sha256_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BinaryField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;__save__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__save__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compute_sha256_hash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;compute_sha256_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;json_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="s2"&gt;&amp;quot;start_at&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="s2"&gt;&amp;quot;end_at&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;               &lt;span class="s2"&gt;&amp;quot;fancy_field&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;      &lt;span class="c1"&gt;# Forces datetime to use timestamp due to inconsistency&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="c1"&gt;# in timezone format.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;start_at&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;end_at&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end_at&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;      &lt;span class="n"&gt;json_repr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;sort_keys&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;         &lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DjangoJSONEncoder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_repr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;sha256_hash&lt;/tt&gt; is unique and shouldn’t allow null values, but with
the &lt;tt class="docutils literal"&gt;blank=True&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;null=True&lt;/tt&gt; attributes, it can have null
values. It’s needed then to populate the existing values if there are
some.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if there is existing data in the table?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;tt class="docutils literal"&gt;sha256_hash&lt;/tt&gt; is unique and shouldn’t allow null values, but with
the &lt;tt class="docutils literal"&gt;blank=True&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;null=True&lt;/tt&gt; attributes, it can have null
values. It’s needed then to populate the existing values if there are
some.&lt;/p&gt;
&lt;p&gt;In order to do that, we change the attribute to allow null values :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;start_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;end_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;fancy_field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CharField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="n"&gt;sha256_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BinaryField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;      &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;   &lt;span class="err"&gt;…&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;After that, we can populate the value with a django command in by
filtering the existing Event table where the field &lt;tt class="docutils literal"&gt;sha256_hash&lt;/tt&gt; is
null, and call the method in order the create the &lt;tt class="docutils literal"&gt;sha256_hash&lt;/tt&gt; value
with the method &lt;tt class="docutils literal"&gt;compute_sha256_hash&lt;/tt&gt; of the class.&lt;/p&gt;
&lt;p&gt;That’s it for me!&lt;/p&gt;
</content><category term="til"></category><category term="til"></category><category term="django"></category></entry><entry><title>DjangoCon Europe 2023: from attendee to organizer</title><link href="https://sarahabd.com/blog/djangocon-europe-2023-from-attendee-to-organizer" rel="alternate"></link><published>2023-06-14T14:36:00+02:00</published><updated>2023-06-14T14:36:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2023-06-14:/blog/djangocon-europe-2023-from-attendee-to-organizer</id><summary type="html">&lt;p class="first last"&gt;Hi there, I hope you’re fine. A few weeks ago, I was at DjangoCon Europe in Edinburgh...&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, I hope you’re fine. A few weeks ago, I was at DjangoCon Europe in Edinburgh.
I’m not sure I have completely recovered from tiredness, but it was awesome!&lt;/p&gt;
&lt;p&gt;I’m hooked on this event. My first DjangoCon was in 2021 in remote, due to COVID, and many
people told me “it’s really different in real life, you should definitely try once”.&lt;/p&gt;
&lt;p&gt;And… I did!&lt;/p&gt;
&lt;p&gt;I participated in DjangoCon Europe last year in Porto, it was amazing.
I really liked the conference and meeting people, some of them that I have talked to virtually,
so there was real joy seeing them in person. It was awesome. This conference helped me to become
more involved in the community and learn so many things.
To be honest, I don’t have the best English but I was able to understand and be understood.
If you have never been to a DjangoCon, you should definitely go to one. It’s truly worth it.&lt;/p&gt;
&lt;p&gt;What you need to know is that each DjangoCon Europe is run by volunteers, and the chairs have
to send a proposal to the &lt;a class="reference external" href="https://www.djangoproject.com/foundation/"&gt;Django Software Foundation&lt;/a&gt;
(DSF) for approval. This conference almost did not happen if you see the DSF’s post about it.
I didn’t want that to happen so I proposed myself as a volunteer. I joined the current team especially
for the website and be part of the Code of Conduct team 💖&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="2023 CoC Team, from left to right, Thibaud Colas, Sage Abdullah, me and Tom Carrick holding the CoC Sign" src="../images/coc-team-2023.jpg" /&gt;
&lt;p class="caption"&gt;© 2023 Thibaud Colas CC BY-NC-SA - CoC Team of DjangoCon 2023&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Being an organizer is a different way of fun. You don’t enjoy the conference the same way, it can be
exhausting, but you really enjoy the fact of seeing the conference happening and being a success
especially when you know all things that happened behind the scenes.&lt;/p&gt;
&lt;p&gt;When you look at people:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;meeting and laughing together&lt;/li&gt;
&lt;li&gt;finding their future job&lt;/li&gt;
&lt;li&gt;finding new friends&lt;/li&gt;
&lt;li&gt;finding help for a specific project&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's a priceless joy ✨&lt;/p&gt;
&lt;p&gt;I learn many things by being “on the other side”.&lt;/p&gt;
&lt;p&gt;I didn't understand how hard it is to get a visa depending on the country you're coming from.
The rules are always different. I didn’t imagine how it can cost so much to host an event
virtually when you have limited funds. Each detail counts, when trying to make the best event for everyone.&lt;/p&gt;
&lt;p&gt;I’m really glad to be part of this community, and I hope to do my best to welcome people
and be friendly as much as I've been welcomed myself.&lt;/p&gt;
&lt;p&gt;If you would like to give back to Django and the community, you should consider DjangoCon
Europe 2024 as a way to do so. Being an organizer or a volunteer is a great way to contribute,
and it doesn't require the ability to code.&lt;/p&gt;
&lt;p&gt;I will end this post by saying that “I joined a conference, I stayed for the community” 💚&lt;/p&gt;
</content><category term="blog"></category><category term="django"></category><category term="djangocon"></category><category term="reflexion"></category></entry><entry><title>Migration from Gatsby to Pelican</title><link href="https://sarahabd.com/blog/migration-from-gatsby-to-pelican" rel="alternate"></link><published>2023-04-21T18:00:00+02:00</published><updated>2023-04-21T18:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2023-04-21:/blog/migration-from-gatsby-to-pelican</id><summary type="html">&lt;p class="first last"&gt;From JS to Python, migration static website generation, Gatsby to Pelican&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi here... it's been a while, first post of 2023 yay!
I have so much to talk about but I'll start with the first
topic that took me a long time to write about: my blog.&lt;/p&gt;
&lt;p&gt;I switched frameworks from &lt;a class="reference external" href="http://Gatsby.js"&gt;Gatsby.js&lt;/a&gt;
to &lt;a class="reference external" href="https://getpelican.com/"&gt;Pelican&lt;/a&gt;.&lt;/p&gt;
&lt;div class="section" id="why-migrate-my-blog"&gt;
&lt;h2&gt;Why migrate my blog ?&lt;/h2&gt;
&lt;p&gt;Good question, as I’m doing more and more python, it
seems more logical to have a blog in python.
Besides, it’s simpler to maintain since I
use the language everyday. I also wanted to have fewer
dependencies.&lt;/p&gt;
&lt;p&gt;My website with Gatsby had many dependencies, you can
see that with my &lt;cite&gt;package.json&lt;/cite&gt;. Now compare that to
the &lt;cite&gt;requirements.txt&lt;/cite&gt;.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="package.json dependencies vs requirements.txt" src="../images/dependencies.png" /&gt;
&lt;p class="caption"&gt;package.json dependencies vs requirements.txt dependencies&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, the change is huge, it's the dependencies
and dev-dependencies without displaying sub-dependencies.&lt;/p&gt;
&lt;p&gt;I needed to move to Gatsby V3 because my project had too
many dependencies which I cannot update. Some are simply
old dependencies that are no longer maintained.&lt;/p&gt;
&lt;p&gt;Otherwise, I had to upgrade my Gatsby project and I had
too many dependencies conflicts since I used a starter
in order to create my blog and the starter is not fully
compatible with latest versions of Gatsby. I know how it
can be hard to maintain a project, especially when you're
alone. I could have contributed but i’m not doing enough
Gatsby to do so in my opinion.&lt;/p&gt;
&lt;p&gt;I finally decided to move to something else.&lt;/p&gt;
&lt;p&gt;I choose to use Pelican, it’s pretty nice. There are
plugins to improve your website and I used one of them to
import existing content from another website. I used it
to move my blog, it’s great! You have the full documentation
&lt;a class="reference external" href="https://docs.getpelican.com/en/latest/importer.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used a custom theme, created by me, to have the
style I wanted. I made it correspond to my previous blog so that
people won’t notice I changed to Pelican. You can find already
built-in &lt;a class="reference external" href="https://github.com/getpelican/pelican-themes"&gt;themes&lt;/a&gt;
or basic theme to create your own theme from. You can get some
guidance ton creating your own theme in the documentation.&lt;/p&gt;
&lt;p&gt;So I started from an existing theme and I change the following:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Review templates to correspond to what I want&lt;/li&gt;
&lt;li&gt;Add missing pages&lt;/li&gt;
&lt;li&gt;Change my CSS style and JavaScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fun part was to change the needed things from
React.js to pure JS to get less dependencies and simple
code because I'm missing some things in my website:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;The animation on the homepage&lt;/li&gt;
&lt;li&gt;The toggle theme for dark mode&lt;/li&gt;
&lt;li&gt;Few JS for customisation (accessibility tweak for aria-label)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that was done, I added some plugins to improve the
website like SEO, or posts related in an article,
you can find the
&lt;a class="reference external" href="https://github.com/getpelican/pelican-plugins"&gt;plugins in the pelican organization&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And that’s it ! ✨&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="examples"&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;p&gt;I know some of you will say, cool Sarah but are there
other websites using Pelican ?&lt;/p&gt;
&lt;p&gt;Yes, there are ! These are the people I know that use
Pelican, but I imagine there are other websites:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Adam Johnson - &lt;a class="reference external" href="https://adamj.eu/"&gt;https://adamj.eu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Julien Palard - &lt;a class="reference external" href="https://mdk.fr/"&gt;https://mdk.fr/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Justin Mayer, creator of Pelican - &lt;a class="reference external" href="https://justinmayer.com/"&gt;https://justinmayer.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Paolo Melchiorre - &lt;a class="reference external" href="https://www.paulox.net/"&gt;https://www.paulox.net/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tom Carrick - &lt;a class="reference external" href="https://carrick.eu/"&gt;https://carrick.eu/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="learning-and-improvements"&gt;
&lt;h2&gt;Learning and improvements&lt;/h2&gt;
&lt;p&gt;This migration was not as difficult as I expected.
I did it in a few days split up on my free time that
I had because I didn't have much time for it, but I
think I could have done it faster. Too many stuff to
do, not enough time.&lt;/p&gt;
&lt;p&gt;It was fun to create the theme for the blog and see
how Pelican generates templates, it’s really nice.
Besides, I added some categories and a TIL section, I
need to add other articles but that’s another point.
Pelican makes it easy to create categories and
update/remove some stuff as you want.
It’s easily customizable to fit your needs.&lt;/p&gt;
&lt;p&gt;Having less dependencies is clearly a good point
for me, less issues and better for maintaining.
I guess I’m like many people who like their blog
but can’t dedicate much time  to it.&lt;/p&gt;
&lt;p&gt;Pelican is really simple to use, I'm not used to
writing in &lt;cite&gt;rst&lt;/cite&gt; but it doesn't change much from &lt;cite&gt;markdown&lt;/cite&gt;.
Note that you can change the type of the articles
if needed, but most  documentation in open source
for Python use &lt;cite&gt;rst&lt;/cite&gt; so it's not a big deal for me.&lt;/p&gt;
&lt;p&gt;I also have time to improve a bit the accessibility
of my blog, clearly not completely done but I had
time to make few corrections, which is cool.&lt;/p&gt;
&lt;p&gt;I can now do draft articles, which is really cool
because I ask people to read articles when they
are willing to do so, since I’m not a native English
speaker. So, you can’t find my blog on GitHub,
sorry for that.&lt;/p&gt;
&lt;p&gt;I recommend Pelican, I don’t have any drawbacks so far.&lt;/p&gt;
&lt;p&gt;Next step will be to improve accessibility again
and add more articles of course !&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category></entry><entry><title>TIL: Global gitignore</title><link href="https://sarahabd.com/til/global-gitignore" rel="alternate"></link><published>2022-07-12T10:10:00+02:00</published><updated>2022-07-12T10:10:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2022-07-12:/til/global-gitignore</id><summary type="html">&lt;p class="first last"&gt;Hi there! I found out that you can configure git to exclude files or folders globally and this is useful so that the project gitignore is…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there!&lt;/p&gt;
&lt;p&gt;I found out that you can configure git to exclude files or folders
globally and this is useful so that the project gitignore is based only
on that and not on the operating system or editor of each team member.&lt;/p&gt;
&lt;p&gt;Guess what, you can ignore things globally on your end and you don’t
need to commit this in the gitignore of the project. I’ll tell you how!&lt;/p&gt;
&lt;p&gt;First of all, you need to create a file in the home directory, we can
call it with any name we want but just to know easily what it is, let’s
call it: &lt;tt class="docutils literal"&gt;.gitignore_global&lt;/tt&gt;.&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
touch&lt;span class="w"&gt; &lt;/span&gt;~/.gitignore_global
&lt;/pre&gt;
&lt;p&gt;And then add in the file all the things you want to exclude:&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
.DS_Store&lt;span class="w"&gt;
&lt;/span&gt;.vs_code
&lt;/pre&gt;
&lt;p&gt;This is mine, I use Mac and Vs Code, but you need to match it with your
&lt;strong&gt;operating system and your editor files.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally, configure git to know that the global files to exclude are in
this path:&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;--global&lt;span class="w"&gt; &lt;/span&gt;core.excludesfile&lt;span class="w"&gt; &lt;/span&gt;~/.gitignore_global
&lt;/pre&gt;
&lt;p&gt;For windows users, it’s slightly different:&lt;/p&gt;
&lt;pre class="code sh literal-block"&gt;
git&lt;span class="w"&gt; &lt;/span&gt;config&lt;span class="w"&gt; &lt;/span&gt;--global&lt;span class="w"&gt; &lt;/span&gt;core.excludesfile&lt;span class="sb"&gt;``&lt;/span&gt;%USERPROFILE%&lt;span class="se"&gt;\.&lt;/span&gt;gitignore_global
&lt;/pre&gt;
&lt;p&gt;That’s it for now! I hope it will be useful for someone :)&lt;/p&gt;
</content><category term="til"></category><category term="til"></category><category term="howto"></category></entry><entry><title>TIL: Accessibility resources</title><link href="https://sarahabd.com/til/accessibility-resources" rel="alternate"></link><published>2022-05-07T10:00:00+02:00</published><updated>2022-05-07T10:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2022-05-07:/til/accessibility-resources</id><summary type="html">&lt;p class="first last"&gt;Hi there, I decided to start TIL (Today I Learned) series ! Rodrigo, author of Mathspp blog, give me envy to do so with his TIL series…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there,&lt;/p&gt;
&lt;p&gt;I decided to start TIL (Today I Learned) series !&lt;/p&gt;
&lt;p&gt;Rodrigo, author of &lt;a class="reference external" href="https://mathspp.com/"&gt;Mathspp&lt;/a&gt; blog, give me envy
to do so with his TIL series, as I told him, I will do that to help me
to remind me some stuff and share what I discovered to everyone who can
be interested on. I’m dedicating my first TIL of a great series to him I
hope.&lt;/p&gt;
&lt;p&gt;I started to create a dark mode for Django project and I face to an
interesting issue : accessibility.&lt;/p&gt;
&lt;p&gt;This is something I’m aware of, but I discovered I have so many things
to learn ! Even my website is really bad for accessibility.. but I
learned some ressources very useful which deserve to be written
somewhere.&lt;/p&gt;
&lt;p&gt;Accessibility concern many cases : &lt;em&gt;Tritanopia&lt;/em&gt;, &lt;em&gt;Deuteranomaly&lt;/em&gt; and so
on.&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://whocanuse.com/"&gt;Whocanuse&lt;/a&gt;, is based on the same purpose of
&lt;a class="reference external" href="https://caniuse.com/"&gt;Caniuse&lt;/a&gt; but for accessibility and contrast.&lt;/p&gt;
&lt;p&gt;It’s really useful to see the simulation of color for each type of
vision and contrast with another color. It really helps me to better
adjust color contrast.&lt;/p&gt;
&lt;p&gt;Note: you can also see color contrast and ratio in devtools of Chrome :&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="devtools chrome contrast" src="../images/devtools-chrome.png" /&gt;
&lt;p class="caption"&gt;devtools chrome contrast&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You also have &lt;a class="reference external" href="https://kontrasto.netlify.app/"&gt;Kontrasto&lt;/a&gt;, created by
Thibaud Colas, which have a deep interest in accessibility 🙂&lt;/p&gt;
&lt;p&gt;Really nice to see a way to improve accessibility with images.&lt;/p&gt;
&lt;p&gt;I also discovered &lt;a class="reference external" href="https://webaim.org/resources/linkcontrastchecker/"&gt;Link Contrast
Checker&lt;/a&gt; which is
a website to see the contrast for links to be sure there are no
violation for accessibility.&lt;/p&gt;
&lt;p&gt;I find &lt;a class="reference external" href="https://www.a11yproject.com/checklist/"&gt;accessibility
checklist&lt;/a&gt; which can be a
good start to make you website more inclusive and see some point you
missed.&lt;/p&gt;
&lt;p&gt;As I am a big fan of pipelines, there are also tools to check
accessibility with desktop extension or in continuous integration:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://www.deque.com/axe/"&gt;aXe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://pa11y.org/"&gt;pa11y&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s it for now! I hope it will be useful for someone.&lt;/p&gt;
</content><category term="til"></category><category term="til"></category><category term="accessibility"></category><category term="resources"></category></entry><entry><title>2021, year in review</title><link href="https://sarahabd.com/blog/2021-year-in-review" rel="alternate"></link><published>2022-01-30T10:00:00+01:00</published><updated>2022-01-30T10:00:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2022-01-30:/blog/2021-year-in-review</id><summary type="html">&lt;p class="first last"&gt;Hi there, it's have been a while... First of all, I want to say happy new year to you, best wishes !! Thank you to Katherine Michel and…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it’s have been a while… First of all, I want to say happy new
year to you, best wishes !!&lt;/p&gt;
&lt;p&gt;Thank you to &lt;a class="reference external" href="https://github.com/KatherineMichel"&gt;Katherine Michel&lt;/a&gt;
and &lt;a class="reference external" href="https://github.com/dawnwages"&gt;Dawn Wages&lt;/a&gt; for inspiring me to do
a Year in Review blog post!&lt;/p&gt;
&lt;div class="section" id="tl-dr"&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;This year wasn’t my best year but I success to do things I can’t imagine
do.&lt;/p&gt;
&lt;p&gt;My highlights for the year have been:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Attending to DjangoCon Europe and US&lt;/li&gt;
&lt;li&gt;Do a lightning talk&lt;/li&gt;
&lt;li&gt;Pass Hacktoberfest challenge&lt;/li&gt;
&lt;li&gt;Make a contribution to a huge project&lt;/li&gt;
&lt;li&gt;Discover and be part of an amazing community&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class="section" id="learning-and-improvements"&gt;
&lt;h2&gt;Learning and improvements&lt;/h2&gt;
&lt;p&gt;I learn a lot this year, by trying things, reading, and do mistakes of
course. I read &lt;a class="reference external" href="https://adamchainz.gumroad.com/l/suydt"&gt;the book of Adams Johnson about
testing&lt;/a&gt;, which is really
interesting. I discovered I had to change some habits and improve some
projects.&lt;/p&gt;
&lt;p&gt;I’m trying to be more involved in things which I care about or I have an
interest in, for example, testing or Open Source Software.&lt;/p&gt;
&lt;p&gt;I also learn by interacting with people, even though I still have some
difficulty understanding everything in English since I am not fluent but
close too!&lt;/p&gt;
&lt;p&gt;I discovered many things in 2021, there are so many resources :
newsletter, podcast, twitter accounts (yeah really), let me list some of
them :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://anchor.fm/djangogirls"&gt;Django Girls podcast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://pycoders.com/"&gt;Pycoder’s weekly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://twitter.com/treyhunner?t=iMH0ONBeIKZmXz2zgiRzkQ&amp;amp;s=09"&gt;Trey
hunner&lt;/a&gt;
twitter account&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://adamj.eu/books/"&gt;Adams Johnson books&lt;/a&gt; and
&lt;a class="reference external" href="https://adamj.eu/tech/"&gt;his blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And conferences, even for past years are really interesting. I
definitely recommend you to check out!&lt;/p&gt;
&lt;p&gt;I also discovered I can inspire others, even I don’t think I did
something amazing as other great people of the dev world but you can
inspire even on things that don’t seem huge.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="conferences"&gt;
&lt;h2&gt;Conferences&lt;/h2&gt;
&lt;p&gt;I have attend to my first conference, DjangoCon Europe, and gave my
first lighting talk ! &lt;a class="reference external" href="https://sarahabd.com/blog/djangocon-europe-2021-thoughts/"&gt;I have wrote a post
here&lt;/a&gt;, I
hope I will have a chance to attend to the next one. And in real life,
so many amazing people have told me that it’s a different experience and
I really want to see that and see the people I talk to, so many times in
the virtual haha.&lt;/p&gt;
&lt;p&gt;I also attend to DjangoCon US, it was very nice but I didn’t attend so
long due to hours. I wanted to help the organizers but I didn’t have
time to do so. If you want to contribute to the community, this is a way
to do it. Many people think, it’s all about code, but there are so many
things to do besides coding for contribution.&lt;/p&gt;
&lt;p&gt;I hope I will be able to do more meetups and exchange with people (in
real life would be even better!).&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="hacktoberfest-as-maintainer"&gt;
&lt;h2&gt;Hacktoberfest as maintainer&lt;/h2&gt;
&lt;p&gt;I have done hacktoberfest for the second time, but this time I was
contributor and also maintainer, thanks to
&lt;a class="reference external" href="https://github.com/funbeedev"&gt;Fum&lt;/a&gt;. This is a great experience, even
I didn’t imagine how it can be exhausting. As a contributor you want
things to happen quickly, but as a maintainer, it’s nice to see the
engagement of people but so many things to do and some time people
answer like the project is your only life, and I can tell you: this is
totally NOT the case !&lt;/p&gt;
&lt;p&gt;Despite that, I have learned so many things by reviewing: see things in
another way, or dig in some subject I didn’t know much before.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="individuals-contributions"&gt;
&lt;h2&gt;Individuals contributions&lt;/h2&gt;
&lt;p&gt;I guess this is my best year for contributing to open source, I
contributed to many projects. From small contributions to big ones. I
contributed to a big project: Django. It was amazing, I also learned
while doing it. It’s not an impressive contribution, but I hope it will
be useful to everyone who uses this amazing framework! I hope to make
more contributions, especially in the python ecosystem this new year.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="reminder-to-myself"&gt;
&lt;h2&gt;Reminder to myself&lt;/h2&gt;
&lt;p&gt;2021 I tried things I didn’t think I would have done. If I have piece of
advice to tell, it will be :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Be more organized&lt;/li&gt;
&lt;li&gt;Try your best, if it’s not perfect, that’s fine&lt;/li&gt;
&lt;li&gt;Contribute, help, write. Sometimes you think it’s stupid or useless,
but it’s not for someone else&lt;/li&gt;
&lt;li&gt;Exchange is gold. You can learn things from someone and the person
can also learn from you&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category></entry><entry><title>Thoughts on DjangoCon Europe 2021</title><link href="https://sarahabd.com/blog/djangocon-europe-2021-thoughts" rel="alternate"></link><published>2021-06-07T12:00:00+02:00</published><updated>2021-06-07T12:00:00+02:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2021-06-07:/blog/djangocon-europe-2021-thoughts</id><summary type="html">&lt;p class="first last"&gt;Hi there, it has been a while since my last post, but I' m now returning from a great conference: DjangoCon Europe. It was my first virtual…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, it has been a while since my last post, but I’ m now returning
from a great conference: DjangoCon Europe.&lt;/p&gt;
&lt;p&gt;It was my first virtual conference. Thanks to the organizers, it was
well done despite the difficult circumstances. We had a
&lt;a class="reference external" href="https://gather.town/"&gt;gather.town&lt;/a&gt; to meet people, talks hosted in
loudswarm, which worked great! It was very interesting. There were great
talks and met amazing people!&lt;/p&gt;
&lt;p&gt;I’m also exhausted lol. I guess it’s another experience as I imagine and
due to the return of people who did it in real life. I hope to have the
ability to attend to another one in person. As people said, you come for
the syntax and stay for the community!&lt;/p&gt;
&lt;p&gt;I gave my first lightning talk at the DjangoCon: “Run Django tests with
GitHub Actions” which was a little introduction to GitHub Actions and
how to use it with Docker services. I’m completely nervous about things
like that but I did it. I’m happy I received some positive feedback. I
know also what to improve if I choose to undertake the experience again
🙂&lt;/p&gt;
&lt;p&gt;If you have one in mind, go for it. You will never regret and it’s a
good experience. You will help someone or make someone discover
something that you didn’t imagine you could. For the sprints, it was
complicated for me to manage the two days, but I was able to be mentor
for DjangoGirls on Saturday. It was a good experience for me.&lt;/p&gt;
</content><category term="blog"></category><category term="django"></category><category term="djangocon"></category><category term="reflexion"></category></entry><entry><title>First contribution to open source, hacktoberfest !</title><link href="https://sarahabd.com/blog/first-contribution-hacktoberfest" rel="alternate"></link><published>2020-11-03T09:08:00+01:00</published><updated>2020-11-03T09:08:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2020-11-03:/blog/first-contribution-hacktoberfest</id><summary type="html">&lt;p class="first last"&gt;First participation, first contribution to open source. Yeah ! Yes, I finished my first the Hacktoberfest challenge, thanks to Digital Ocean…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;First participation, first contribution to open source. Yeah !&lt;/p&gt;
&lt;p&gt;Yes, I finished my first the Hacktoberfest challenge, thanks to Digital
Ocean, Dev.to and Intel. If you don’t know what I’m talking about, just
check &lt;a class="reference external" href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest details&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I always wanted to contribute to an open source project. But there
always seemed to be obstacles: first thoughts:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Which project should I choose out of the ocean of possible
repositories?&lt;/li&gt;
&lt;li&gt;How can I make a good pull request for a project?&lt;/li&gt;
&lt;li&gt;Issues usually seem to need specific understanding of how the
projects develop&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yeah, I know what your are thinking: &lt;em&gt;she might be crazy&lt;/em&gt; or maybe just
&lt;em&gt;I feel the same&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I think it’s normal to think whenever you use a good open source
project, you want to contribute to it in the future. Open source is
incredible. There are so many projects that are used by so many people.&lt;/p&gt;
&lt;p&gt;I have so much respect for open source project maintainers because many
or maybe most of our personal or professional projects would fail
without them.&lt;/p&gt;
&lt;p&gt;Hacktoberfest is one of the best way to start contributing to open
source projects. Their site lists an extensive resources and provides
information for contributing regardless of whether you a beginner or a
seasoned developer. And if you follow the specific CONTRIBUTING.md for
in the open source repository, you can’t be lost (normally).&lt;/p&gt;
&lt;p&gt;Don’t hesitate to reach out to the maintainers or other contributors to
ask questions if needed, as well as checking labels, and spending some
time carefully reading issues.&lt;/p&gt;
&lt;p&gt;If you’re a beginner you can check start by checking this link which
will suggest some good things to get started with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="http://issuehub.io/?label%5B%5D=good+first+issue"&gt;issuehub.io&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even if the Hacktoberfest has finished this year, now is still a great
time to make your first contributions.&lt;/p&gt;
&lt;p&gt;I contributed to 2 projects:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/inspirezonetech/TeachMePythonLikeIm5"&gt;TeachMePythonLikeIm5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="https://github.com/inspirezonetech/TeachMeBashLikeIm5"&gt;TeachMeBashLikeIm5&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was my first Hacktoberfest event and I have loved this experience.
I can’t fully explain but the satisfaction that comes from contributing
to something that can be useful to others feels great. It’s also time to
discover other projects, by searching or through people who share their
experiences and learn new things, of course.&lt;/p&gt;
&lt;p&gt;I will continue to contribute ❤️&lt;/p&gt;
&lt;p&gt;Unfortunately I didn’t officially complete the Hacktoberfest challenge
due to an “&lt;a class="reference external" href="https://github.com/digitalocean/hacktoberfest/issues/724"&gt;intented
behaviour&lt;/a&gt;”
which now prohibits certain repositories from being eligible.&lt;/p&gt;
&lt;p&gt;So just beware, if you have participated this year and your PRs are
still in review, be careful, the flaw can still happen to you. &lt;a class="reference external" href="https://dev.to/funbeedev/check-your-hacktoberfest-profile-a-flaw-could-have-reversed-your-completion-of-the-challenge-without-you-knowing-it-2kg6"&gt;Fum
explain all in his blog&lt;/a&gt;.
Regardless this is less important than having first taken the plunge
into making contributions to open source projects — which is really the
thing at the core of Hacktoberfest.&lt;/p&gt;
&lt;p&gt;See you maybe next year!&lt;/p&gt;
</content><category term="blog"></category><category term="open-source"></category><category term="hacktoberfest"></category></entry><entry><title>Manual trigger with Github Actions</title><link href="https://sarahabd.com/blog/manual-trigger-with-github-actions" rel="alternate"></link><published>2020-01-28T22:12:00+01:00</published><updated>2020-01-28T22:12:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2020-01-28:/blog/manual-trigger-with-github-actions</id><summary type="html">&lt;p class="first last"&gt;Hi there, this blog post explains how to manually trigger builds of GitHub actions. Why would you want to do that? Instead of just waiting…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Hi there, this blog post explains how to manually trigger builds of
GitHub actions.&lt;/p&gt;
&lt;div class="section" id="why-would-you-want-to-do-that"&gt;
&lt;h2&gt;Why would you want to do that?&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Instead of just waiting for a code change or a GitHub workflow change?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, for example the last time your build on master ran, maybe some of
the servers used by your build were down (example: npm registry, some
API you’re using for tests, etc..).&lt;/p&gt;
&lt;p&gt;For now &lt;a class="reference external" href="https://github.community/t5/GitHub-Actions/GitHub-Actions-Manual-Trigger-Approvals/td-p/31504"&gt;GitHub says that there’s no way to manually trigger a
build&lt;/a&gt;,
while this question was &lt;a class="reference external" href="https://stackoverflow.com/q/58933155/7087644"&gt;asked on
StackOverflow&lt;/a&gt; and some
people are even using CURL to trigger manual builds.&lt;/p&gt;
&lt;p&gt;But I have found a better way! With my solution, once you’ll have it set
up, the ⭐️ button of your GitHub repository will trigger a build every
time YOU (and only you) will star the repository. You can do that as
many times as you want.&lt;/p&gt;
&lt;p&gt;Yes, it’s a VERY &lt;em&gt;hacky&lt;/em&gt; solution but it works pretty well. ✨&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="how-to-do-manual-trigger"&gt;
&lt;h2&gt;How to do manual trigger&lt;/h2&gt;
&lt;p&gt;Let’s dig into it.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="GIF image that show the use of the star button to trigger manually a workflow" src="https://dev-to-uploads.s3.amazonaws.com/i/6oqnfhr50mczsodhp57c.gif" /&gt;
&lt;/div&gt;
&lt;p&gt;The ⭐️ button is used to launch the workflow if it’s possible, like this.&lt;/p&gt;
&lt;p&gt;Update your workflow file to include:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;started&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;So the workflow will be executed each time you star, or unstar and star
again the repo.&lt;/p&gt;
&lt;p&gt;If we combine that by &lt;a class="reference external" href="https://stackoverflow.com/a/58965362"&gt;a useful advice from
Samira&lt;/a&gt; in Stack Overflow, you
can launch your workflow only if it’s the owner who trigger the action.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;github.actor == github.event.repository.owner.login&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It prevents to execute the action by others and only by maintainers for
example.&lt;/p&gt;
&lt;p&gt;Next you can add your job(s) to do and additional services.&lt;/p&gt;
&lt;p&gt;At the end, we have the following workflow…&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Test&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;started&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;github.actor == github.event.repository.owner.login&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout repository&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v2&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="c1"&gt;#  add more ...&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It’s a starter, so you can adapt it for an existing workflow or start a
new one with this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="few-notes"&gt;
&lt;h2&gt;Few notes&lt;/h2&gt;
&lt;p&gt;There is the possibility to &lt;strong&gt;combine two events&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example you can set your workflow with the watch event and on each
push, to have the both ways.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Test&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;master&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;started&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here it run the process for &lt;strong&gt;each push on master branch and on star of
the repo&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don’t forget&lt;/strong&gt; that if you want to re-run a workflow which have
failed, you can re-run all the checks with a UI button set for a failed
workflow just like that…&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="" src="https://thepracticaldev.s3.amazonaws.com/i/jm4zi3ccyfze9eyndk6g.png:alt:Screenshotoftheactionstabwiththebuttonre-runfailedonthetoprightcorner" /&gt;
&lt;p class="caption"&gt;Screenshot of the actions tab on GitHub&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It depends on what you really want to do.&lt;/p&gt;
&lt;p&gt;Moreover, you can launch the full workflow with the watch event or only
some particular steps if you add a conditional if on a step like this:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Test&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;started&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Checkout repository&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v2&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Step 2&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nt"&gt;if&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;github.actor == github.event.repository.owner.login&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In this case, it will run step 2 only if the repo is starred by the
owner.&lt;/p&gt;
&lt;blockquote&gt;
&lt;strong&gt;Don’t forget&lt;/strong&gt; that the ⭐️ button launch the workflow from the
default branch (master) only.&lt;/blockquote&gt;
&lt;p&gt;Notice that there is permissions to avoid actions in the repository or
to avoid the third party to run your actions in the settings of the
repo.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Screenshot of action permissions with 3 options: &amp;quot;Enable local and third party Actions for this repository&amp;quot;, &amp;quot;Enable local Actions only for this repository&amp;quot; and &amp;quot;Disable Action for this repository&amp;quot;" src="https://thepracticaldev.s3.amazonaws.com/i/r40qoujp9qt08tz9lmyo.png" /&gt;
&lt;p class="caption"&gt;Screenshot of the actions permissions in the settings&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Suggested by &lt;a class="reference external" href="https://dev.to/neilime/comment/nipi"&gt;Emilien Escalle in comments on
dev.to&lt;/a&gt;, we can also configure
the workflow only for collaborators by creating another job which will
be needed to check if it’s a collaborator of the project or the workflow
will fail.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;authorize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;octokit/request-action&amp;#64;v2.0.0&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;GET /repos/:repository/collaborators/${{ github.actor }}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ github.repository }}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nt"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;needs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;authorize&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="w-Error"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="good-to-know"&gt;
&lt;h2&gt;Good to know…&lt;/h2&gt;
&lt;p&gt;GitHub &lt;em&gt;just&lt;/em&gt; &lt;a class="reference external" href="https://github.blog/changelog/2020-01-27-github-actions-api-beta/"&gt;released their action
APIs&lt;/a&gt;
which should allow soon either GitHub or browser extensions to add
“trigger workflow” buttons on their UI.&lt;/p&gt;
&lt;p&gt;I hope you liked this post and special thanks to
&lt;a class="reference external" href="https://dev.to/vvo"&gt;Vincent&lt;/a&gt; who pushed me to write it :)&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="github-actions"></category><category term="howto"></category><category term="testing"></category></entry><entry><title>Relation between middle/senior and junior dev</title><link href="https://sarahabd.com/blog/relation-between-senior-and-junior-dev" rel="alternate"></link><published>2020-01-01T22:12:00+01:00</published><updated>2020-01-01T22:12:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2020-01-01:/blog/relation-between-senior-and-junior-dev</id><summary type="html">&lt;p class="first last"&gt;I've been a teacher and also a learner, so I've got something to tell you. I've heard so many comments like &amp;quot;you're too junior&amp;quot; , &amp;quot;you're…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I’ve been a teacher and also a learner, so I’ve got something to tell
you.&lt;/p&gt;
&lt;p&gt;I’ve heard so many comments like &lt;em&gt;“you’re too junior”&lt;/em&gt;, &lt;em&gt;“you’re not a
middle/senior dev”&lt;/em&gt;. I’m sure you’ve heard that too.&lt;/p&gt;
&lt;p&gt;If you told me that something is impossible, I’m the type of woman that
will try to succeed even if there is only a small chance.&lt;/p&gt;
&lt;p&gt;Yes, I tried to achieve a proficiency level in tech close to the level
of developers who inspired me despite my limited experience.&lt;/p&gt;
&lt;p&gt;The fact is, some people believe that a junior should listen to the
middle/senior dev and that’s all.&lt;/p&gt;
&lt;p&gt;The middle/senior dev is highly qualified and has experience. For sure.&lt;/p&gt;
&lt;blockquote&gt;
But it’s still &lt;strong&gt;an exchange&lt;/strong&gt;.&lt;/blockquote&gt;
&lt;p&gt;Sharing knowledge is not easy for everyone. And when you’re in this
situation, you sometimes have the obligation to explain complexity with
simple words and distill abstract ideas into more digestible ones.&lt;/p&gt;
&lt;p&gt;It’s an art not a science, really.&lt;/p&gt;
&lt;p&gt;We all know that &lt;strong&gt;a developer is always learning&lt;/strong&gt;, even by asking
other devs. Sometimes developers ask things you didn’t think about, or
you just don’t know about, and you also want to know the answer. So
sometimes their question prompts you to research more and helps expand
your knowledge base.&lt;/p&gt;
&lt;div class="section" id="to-you-the-junior-dev"&gt;
&lt;h2&gt;To you the junior dev&lt;/h2&gt;
&lt;p&gt;Don’t think the dev with high skills has no time for you. If he/she is
really busy, add a meeting in his/her calendar. That will show it’s
important for you and you really need this point. It can be the time to
clarify what’s good in your work and what needs to be improved.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Try to find the answer before asking but don’t dedicate too much time
to it&lt;/strong&gt;. If you’re stuck ask for help. You’re losing time, even if it
seems important to do it on your own and get the glory, you could have
done so much more. And when it’s solved in two seconds, it’s much better
not to wait so much time to ask help 😉&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="to-you-the-middle-senior-dev"&gt;
&lt;h2&gt;To you the middle/senior dev&lt;/h2&gt;
&lt;p&gt;Some people admire you in secret, I mean really. Take time to help
junior dev to grow if you have the capacity to do so. It’s also time for
you to challenge yourself and get to know your team better as well.&lt;/p&gt;
&lt;p&gt;From my perspective a great middle/senior dev is not just someone who is
technically proficient but also is someone who can help others to grow.
An experienced dev should &lt;strong&gt;constantly learn to teach others with more
clarity, to better organize their team, and to communicate more
effectively&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And you, what do you think?&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="reflexion"></category></entry><entry><title>Docker services in Github Actions won't have secrets for you</title><link href="https://sarahabd.com/blog/docker-services-in-github-actions" rel="alternate"></link><published>2019-11-17T22:12:00+01:00</published><updated>2019-11-17T22:12:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2019-11-17:/blog/docker-services-in-github-actions</id><summary type="html">&lt;p class="first last"&gt;I explain deeper how is structured an action and how to use docker services in an article but I will focus here more on services. Yeah…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I explain deeper &lt;a class="reference external" href="/blog/create-github-actions-with-docker-services"&gt;how is structured an action and how to use docker
services in an
article&lt;/a&gt; but I will
focus here more on services.&lt;/p&gt;
&lt;p&gt;Yeah, the great fact is you can use Docker containers as services in
Github Actions. 🎉&lt;/p&gt;
&lt;div class="section" id="how-do-we-do-it"&gt;
&lt;h2&gt;How do we do it?&lt;/h2&gt;
&lt;p&gt;Very simple, it is similar to the definition of a service in a
&lt;em&gt;docker-compose.yml&lt;/em&gt; but with far fewer parameters.&lt;/p&gt;
&lt;p&gt;We use the keyword &lt;strong&gt;services&lt;/strong&gt; with:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the definition of the Docker image to be used&lt;/li&gt;
&lt;li&gt;the list of ports to be exposed of the service&lt;/li&gt;
&lt;li&gt;a list of environment variables&lt;/li&gt;
&lt;li&gt;a list of volumes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not all of these elements are required but good to know.&lt;/p&gt;
&lt;p&gt;In concrete terms, it looks like this, for a Postgres service:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;env&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_BD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432/tcp&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Example made by Chris Patterson and &lt;a class="reference external" href="https://dev.to/mscccc"&gt;Mike
Coutermarsh&lt;/a&gt; for PostgreSQL. You can find the
full example with node just
&lt;a class="reference external" href="https://github.com/actions/example-services"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We need the Docker image to launch, the port to expose and the name of
the service. There is a way to transmit environment values or Docker
options as shown in the example above. Sensitive values can be defined
with &lt;a class="reference external" href="https://help.github.com/en/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables"&gt;secret
key&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="full-example"&gt;
&lt;h2&gt;Full example&lt;/h2&gt;
&lt;p&gt;For example we want to do an action which launch tests of our Django
application on each push event.&lt;/p&gt;
&lt;p&gt;The following workflow is implemented:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Test Workflow&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;push&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_BD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Set up Python 3.5.7&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/setup-python&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;python-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;3.5.7&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Install dependencies&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;pip install -r requirements.txt&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;python manage.py test&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here the job tests consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;install Python 3.5.7 on the Ubuntu environment&lt;/li&gt;
&lt;li&gt;install the dependencies&lt;/li&gt;
&lt;li&gt;start the tests with the Postgres database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this example, we still need to override the service values in the
Django settings.py for the connection to the PostgreSQL database like
that :&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;DATABASES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="s1"&gt;'default'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="s1"&gt;'ENGINE'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'django.db.backends.postgresql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="s1"&gt;'NAME'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="s1"&gt;'USER'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'postgres'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="s1"&gt;'HOST'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;       &lt;span class="s1"&gt;'PORT'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;If you have multiple settings for database, you can do with env variable
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;os.environ.get('HOST_NAME')&lt;/span&gt;&lt;/tt&gt; or a conditional settings with
&lt;tt class="docutils literal"&gt;if &lt;span class="pre"&gt;os.environ.get('GITHUB_WORKFLOW')&lt;/span&gt;&lt;/tt&gt; for example.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="few-notes"&gt;
&lt;h2&gt;Few notes&lt;/h2&gt;
&lt;p&gt;It is sometimes necessary to require a service status feedback to
establish a connection. Therefore, an element is defined that checks the
health of the service to know when it is operational (also called a
&lt;em&gt;health check&lt;/em&gt;).&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This one is for postgres but you can find multiple such as
elasticsearch, mysql and so on… In case you don’t have a &lt;strong&gt;health
check&lt;/strong&gt; available, we pause the process execution with the command
sleep, yes it’s not great, I grant you…&lt;/p&gt;
&lt;p&gt;To link the service with the job of the workflow, the &lt;strong&gt;host&lt;/strong&gt; is
needed. In case you’re running your workflow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;em&gt;in the virtual machine&lt;/em&gt;, it will be &lt;strong&gt;localhost&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p class="first"&gt;&lt;em&gt;in a container&lt;/em&gt;, it will be &lt;strong&gt;the name of the service&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Don’t forget&lt;/strong&gt;, you can use Docker services only with a Linux
distribution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;According to the port, to access it on your job(s), it will be like
that:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="l-Scalar-Plain"&gt;${{ job.services.postgres.ports[5432] }}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In the first example, the machine port 5432 is randomly assigned a free
port and accessed.&lt;/p&gt;
&lt;p&gt;Nevertheless, it can be assigned in a fixed way:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here, we have the port 5432 of the service related to the port 5432 of
the machine defined in the action.&lt;/p&gt;
&lt;p&gt;Here you go, you’re ready to use services in your workflow ! 💪&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="github-actions"></category><category term="docker"></category><category term="postgresql"></category><category term="testing"></category></entry><entry><title>How to create Github Actions to run tests with services ?</title><link href="https://sarahabd.com/blog/create-github-actions-with-docker-services" rel="alternate"></link><published>2019-11-05T22:12:00+01:00</published><updated>2019-11-05T22:12:00+01:00</updated><author><name>Sarah Abderemane</name></author><id>tag:sarahabd.com,2019-11-05:/blog/create-github-actions-with-docker-services</id><summary type="html">&lt;p class="first last"&gt;I’ve been digging GitHub Actions since I received access to the beta. GitHub Actions is generally available since November 11, 2019 and I…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;I’ve been digging GitHub Actions since I received access to the beta.
GitHub Actions is generally available since November 11, 2019 and I can
explain to you. 🎉&lt;/p&gt;
&lt;p&gt;&lt;a class="reference external" href="https://tkt.paris/comment-creer-une-action-github-pour-tester-son-application-avec-des-services"&gt;French version of the article&lt;/a&gt;  right
here.&lt;/p&gt;
&lt;div class="figure"&gt;
&lt;img alt="Photo of tree of a project with the commits and a graph Git with three branches" src="https://cdn-images-1.medium.com/max/1024/0*dcmLNHncSQ4306nX" /&gt;
&lt;p class="caption"&gt;Photo by Yancy Min on Unsplash&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="what-is-it"&gt;
&lt;h2&gt;What is it ?&lt;/h2&gt;
&lt;p&gt;Github Action is a solution for continuous integration and continuous
deployment (CI/CD). It’s a new feature from Github, which is displayed
as a tab in your repository. Its operations are triggered by &lt;strong&gt;Git
events such as a commit push&lt;/strong&gt;. In order to create a new sequence of
events to be run on a commit push, we must create a set of commands
which will be carried out according to the specifications of the
project. This service is designed to perform processes automatically and
continuously for collaborative work on a Git repo once implemented. It
should be noted that Github Action is based on Docker, so it’s
recommended to have some knowledge about it to use it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="write-your-action"&gt;
&lt;h2&gt;Write your action&lt;/h2&gt;
&lt;p&gt;An action contains several elements necessary to perform a process: the
&lt;strong&gt;on&lt;/strong&gt; event that corresponds to the Github event: push, pull request,
etc. During the beta however, only the push and pull request triggers
are available.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p-Indicator"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="p-Indicator"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="p-Indicator"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;It is of course possible to define the scope of your action, so it does
specific tasks on certain branches of your repository but not on others.
For example, this may include automatic deployment to a server from the
staging branch but not from the dev branch.&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;branches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;staging&lt;/span&gt;
&lt;/pre&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Then we have the &lt;strong&gt;jobs&lt;/strong&gt;. In practice, a job is a series of steps
performed in an orderly manner. It has 2 important elements: the
environment and the steps to be taken by the service.&lt;/div&gt;
&lt;div class="line"&gt;The &lt;strong&gt;runs-on&lt;/strong&gt; parameter defines the environment in which the action
is performed:&lt;/div&gt;
&lt;/div&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;There are several possible virtual environments for the execution of
your action, this can be useful so that it corresponds to the
specificities of each one. From Ubuntu 19.10 to Windows 2016, you have
the choice 😉&lt;/p&gt;
&lt;blockquote&gt;
It should be noted that each job is performed in a new instance of
the virtual environment.&lt;/blockquote&gt;
&lt;p&gt;So if you want to perform a series of actions with a link between them,
you may want consider doing it in the same job. But it is possible to
create job dependencies with the &lt;strong&gt;need&lt;/strong&gt; parameter:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;job1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;job2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;need&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;job1&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In this case, job2 will only run when job1 has been completed.&lt;/p&gt;
&lt;p&gt;Then, we have all the steps to perform during the process. With a view
to continuous integration, the aim is to launch the tests automatically.
However, a number of elements must be defined before the tests can be
performed!&lt;/p&gt;
&lt;p&gt;This set is defined by the keyword &lt;strong&gt;steps&lt;/strong&gt;. Each step requires at
least one element to be performed, i.e.&amp;nbsp;one of its elements:&lt;/p&gt;
&lt;p&gt;the &lt;strong&gt;uses&lt;/strong&gt; keyword to use a specific element:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;a public action&lt;/li&gt;
&lt;li&gt;an action in the same repository&lt;/li&gt;
&lt;li&gt;an action on the Docker Hub or on the Docker public register&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;the &lt;strong&gt;run&lt;/strong&gt; keyword to launch a command in bash (knowing that there are
several ways to execute a command if necessary)&lt;/p&gt;
&lt;p&gt;Finally, we associate the parameter &lt;strong&gt;name&lt;/strong&gt; to know which step it
represents. An example being always more meaningful, so here is a job to
test a Django project:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Set up Python 3.5.7&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/setup-python&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;python-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;3.5.7&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Install dependencies&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;pip install -r requirements.txt&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;python manage.py test&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here the job tests consist of:&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;install Python 3.5.7 on the Ubuntu environment&lt;/li&gt;
&lt;li&gt;install the dependencies&lt;/li&gt;
&lt;li&gt;start the tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For tests in real conditions, a database is needed, hence the
&lt;em&gt;implementation of services&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class="section" id="add-a-service-to-your-action"&gt;
&lt;h2&gt;Add a service to your action&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;How do we do it?&lt;/em&gt; Very simple, it is similar to the definition of a
service in a docker-compose.yml but with far fewer parameters.&lt;/p&gt;
&lt;p&gt;We use the keyword &lt;strong&gt;services&lt;/strong&gt; with :&lt;/p&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;the definition of the Docker image to be used&lt;/li&gt;
&lt;li&gt;the list of ports to be exposed of the service&lt;/li&gt;
&lt;li&gt;a list of environment variables&lt;/li&gt;
&lt;li&gt;a list of volumes&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="line-block"&gt;
&lt;div class="line"&gt;Not all of these elements are required but good to know.&lt;/div&gt;
&lt;div class="line"&gt;In concrete terms, it looks like this, for a Postgres service:&lt;/div&gt;
&lt;/div&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;env&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_BD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432/tcp&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;We need the Docker image to launch, the port to expose and the name of
the service. There is a way to transmit environment values or Docker
options as shown in the example above. Sensitive values can be defined
with &lt;a class="reference external" href="https://help.github.com/en/github/automating-your-workflow-with-github-actions/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables"&gt;secret
key&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In addition, it is sometimes necessary to require a service status
feedback to establish a connection. Therefore, an element is defined
that checks the health of the service to know when it is operational
(also called a health check). I took up the example made by Chris
Patterson and &lt;a class="reference external" href="https://dev.to/mscccc"&gt;Mike Coutermarsh&lt;/a&gt; for
PostgreSQL.&lt;/p&gt;
&lt;p&gt;In case you don’t have a health check available, we pause the process
execution with the command &lt;strong&gt;sleep&lt;/strong&gt; , yes it’s not great, I grant you…&lt;/p&gt;
&lt;p&gt;All this is very good, but we have to make the link between the service
and our application. We will do it through the port and for the host it
will be &lt;em&gt;localhost&lt;/em&gt; since the service is executed directly in the Ubuntu
machine in our example. Otherwise it would have been the name of the
service.&lt;/p&gt;
&lt;p&gt;In the previous example, the machine port 5432 is randomly assigned a
free port and accessed as follows:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="l-Scalar-Plain"&gt;${{ job.services.postgres.ports[5432] }}&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Nevertheless, it can be assigned in a fixed way:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Here, we have the port 5432 of the service related to the port 5432 of
the machine defined in the action.&lt;/p&gt;
&lt;p&gt;The following workflow is implemented:&lt;/p&gt;
&lt;pre class="code yaml literal-block"&gt;
&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Test Workflow&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;push&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nt"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;POSTGRES_BD&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;postgres&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;5432:5432&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;--health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5&lt;/span&gt;&lt;span class="w"&gt;

   &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/checkout&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Set up Python 3.5.7&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;actions/setup-python&amp;#64;v1&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nt"&gt;python-version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;3.5.7&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Install dependencies&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;pip install -r requirements.txt&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;Run tests&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l-Scalar-Plain"&gt;python manage.py test&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;In our example, we still need to override the service values in the
Django settings.py for the connection to the PostgreSQL database.&lt;/p&gt;
&lt;p&gt;Then the trick is done, just push some code and hope it works. 😉&lt;/p&gt;
&lt;/div&gt;
</content><category term="blog"></category><category term="github-actions"></category><category term="testing"></category><category term="docker"></category><category term="howto"></category><category term="django"></category></entry></feed>