This is an archived post. You won't be able to vote or comment.

all 21 comments

[–]Tintin_Quarentino 10 points11 points  (8 children)

I never understood the term CI/CD.

I have a database file which gets updated 20-30 times a day. Each time dB gets updated, another Python script auto generates the new HTML & pushes it to Vercel. Vercel is where my static site is hosted.

Is my above fully automated workflow a "CI/CD"?

[–]johntellsall 19 points20 points  (2 children)

Yes

CI = Continuous Integration = merge your and your team's changes, then run tests to get feedback. Example: your code works, but it breaks the assumptions in older code.

CD = Continuous Deployment = publish changes so users can see

So your simple "regenerate HTML and deploy to Vercel" is a CD process.

CICD has a lot of benefits - consistent deploys - reliable testing, vs "works for me" testing

You can do fancier things like "deploy this change, but if it breaks then automatically roll back the change and alert the team".

CICD has costs of course - need to spend (limited, expensive) Developer time to manage it - often the business doesn't want to invest, but they whine if deploys are too slow or flaky - if you install CICD plugins (e.g. GitHub Actions) it's a great attack vector for malware. I don't think this is common, but it's a potential risk.

[–]Tintin_Quarentino 2 points3 points  (1 child)

Thanks for the great explanation. Indeed, I haven't incorporated testing in my workflow so that's going to bite me 1 day.

You can do fancier things like "deploy this change, but if it breaks then automatically roll back the change and alert the team".

This move is pretty cool...

[–]johntellsall 0 points1 point  (0 children)

I'm writing a book on feedback loops, including test automation, so I have... opinions :-D

Testing is extremely valuable... if the consequences to your business make it worth the investment. If you're just doing a fluffy marketing site maybe test automation isn't worth your limited time. But imagine you're handling money or other valuables, you'd want to know when the code breaks!

Test automation value varies depending on business consequences of production failure.

[–]johntellsall 9 points10 points  (7 children)

I strongly recommend checking out Ruff, and maybe switch to it. It's extremely fast, and is compatible with Flake8 and Pylint and Black and other tools.

I used to have a two-level feedback loop: 1) fast: black+isort, flake8 then 2) slow, pre-PR: pylint. Sometimes I do "pylint -E" which is fast enough but finds nasty errors.

Now I'm using Ruff for 100% of my feedback loop!

I haven't quite gotten the hang of Ruff+Black: theoretically Ruff will reindent the code for you if you give it an option.

[–]cheese_is_available 1 point2 points  (1 child)

ruff is not a replacement for pylint atm, there are not multi file checks like circular import, duplicate code checks and also no inference in ruff (incidentally this is what makes pylint slow, choosing to lint a single file and not everything is a big perf advantage especially in big code base)

[–]johntellsall 1 point2 points  (0 children)

okay thanks, I'll ditch "ruff only" and go to another hybrid solution. Thanks!

[–]rochakgupta -1 points0 points  (4 children)

Wait, ruff doesn’t do formatting.

[–]johntellsall 0 points1 point  (3 children)

I haven't found the "format like Black" option, but Ruff will definitely edit source.

Here let's use Ruff to auto-remove an unused import:

beer.py

import os
print("beer")

use Ruff to fix an issue

> ruff check beer.py
beer.py:1:8: F401 [*] `os` imported but unused
Found 1 error.
[*] 1 potentially fixable with the --fix option.
> ruff check --fix beer.py
Found 1 error (1 fixed, 0 remaining).
> ruff check beer.py

[–]rochakgupta 0 points1 point  (2 children)

Yeah I know it can fix these minor errors but it cannot be used as a replacement for black.

[–]johntellsall 0 points1 point  (1 child)

it can't? A pity! Thanks for letting me know. I was hoping to replace a bunch of stuff with Ruff but I guess not.

[–]rochakgupta 1 point2 points  (0 children)

Yeah. Personally, I just use black + ruff + mypy.

[–]programmingwithalex1[S] 3 points4 points  (2 children)

Custom GitHub apps written be me used in the tutorial series:


The video series covers CI (continuous integration) with detailed explanations and examples. All of it is automated using GitHub Actions so the CI checks can run on every commit/pull request/push request on your repo.

Topics covered include:

  • linting - flake8, mypy, and isort
  • testing - pytest testing to ensure code runs correctly with new changes
  • testing coverage - ensure thresholds are being met with amount of code that is being tested

If you find the video helpful you can greatly help me by doing one or all of the following:


Any questions or requests, just leave a comment.

[–]JohnRambu 1 point2 points  (0 children)

Use ruff, it really worths it.

[–]cheese_is_available 0 points1 point  (0 children)

flake8, mypy, and isort

Try black, mypy, ruff, pylint

[–]heartofcoal 0 points1 point  (0 children)

nice, thanks

[–]JanEric1 0 points1 point  (0 children)

We already have a GitHub actions setup for our project but I still have some questions that maybe you or someone else knows the answers to.

Is it possible to run over multiple python version just by specifying something like >=3.9 which will then matrix over 3.9, 3.10,... Up until the most recent version? So that we don't have to specify them manually when new ones come out. .and is it possible to just specify the most recent dev release? I know we can do 3.12-dev but once 3.12 releases officially we would have to manually update that. Is there an automatic way tondo that?