M4R774 / bobweb2

Telegram botti piristämään elämää
MIT License
8 stars 1 forks source link
django docker-compose python telegram-bot

Quality Gate Status Lines of Code Coverage Technical Debt Vulnerabilities

Security Rating Reliability Rating Maintainability Rating

bobweb2

Bobweb on erään kaveriporukan oma chättibotti.

Joka päivä henkilö joka sanoo ekana 1337 klo 1337 saa pisteen. Lisäksi, kerran viikossa on mahdollista ansaita ylennys mergeämällä muutos tämän repon main haaraan.

Tässä on nähty paljon vaivaa ja tehty tosi hieno CI/CD putki.

Bottia ajetaan Raspberry Pi 2B:llä.

Projekti on jaettu kahteen osioon: Bob ja Web. Bob on Telegram botin toteutus, Web on djangolla toteutettu webbisivu.

"Only way to go fast is to go well" - Uncle Bob

CI/CD

Projektissa on käytössä GitHub Actions ja Sonar Cloud quality gate. Pull requestin ja jokaisen siihen kohdistuvan puskun yhteydessä suoritetaan:

Kun main-haaraan pusketaan muutoksia tapahtuu sekä koko projektin Sonar laatuanalyysi, että automaattinen muutosten deployaaminen tuotantoon. Deployaamisessa buildataan projektista valmiit docker imaget alustoille [amd64, armv7] ja näistä pusketaan imaget DockerHubiin. Tuotantoympäristö tarkistaa uusimman version viiden minuutin välein ja uudelleenkäynnistää botin uusimmalla versiolla mikäli sellainen on saatavilla.

Ominaisuudet

Telegram botti sisältää pitkän listan erilaisia kivoja ominaisuuksia. Suurin osa näistä ominaisuuksista on nähtävissä /help komennolla (WIP) Tällä hetkellä ainakin nämä ominaisuudet löytyvät:

Muita ominaisuuksia:

Paikallinen kehitysympäristö

"Mummo-ohjeet", miten Bobista saa kopion käyntiin omalle koneelle tai miten esimerkiksi yksikkötestit ajetaan.

Esivaatimukset:

Sovellusta voi ajaa joko paikallisesti asennetuilla ohjelmilla tai Docker-kontissa. Suositeltu kehitysympäristö on PyCharm, josta löytyy myös ilmainen community edition.

Asennettujen sovellusten vaatimukset

Botin ajaminen omalla tietokoneella:

Botin ajamiseen paikallisesti on 2 vaihtoehtoa. Vaihtoehto 1 on käyttää paikallista ympäristöä, missä python ja botin käyttämät riippuvuudet on asennettu levylle käyttäjän käyttöjärjestelmän tiedostohierarkiaan. Vaihtoehto 2 on käyttää Docker-kontteja, jolloin kaikki bottiin liittyvä asennus tehdään eristetyn kontin sisällä. Molemmissa on omat hyvät ja huonot puolensa. Lähtökohtaisesti on helpompi ajaa bottia paikallisesti, mutta Docker konttien käyttö eristää bottiin liittyvät asiat omaan konttiinsa, jolloin muut asennetut python versiot tai kirjastot eivät aiheuta ongelmia.

Koska tietokanta luodaan Djangon migraatioilla, tarvii Docker-konttien vaihtoehdossa valmistella projekti osittain paikallista suoritusta varten.

Yhteiset vaiheet

  1. Asenna Git, PyCharm, Python 3.10 tai uudempi, Pip3 ja venv
  2. Aseta julkinen SSH-avain Githubin asetuksista profiiliisi. Tätä ei tarvita projektin kloonaamiseen, vaan muutosten puskemiseen. Ohjeet tähän löytyy Githubin omasta oppaasta
  3. Kloonaa repository omalle koneellesi
    • git clone git@github.com:M4R774/bobweb2.git
  4. Jos et käytä PyCharmia, joudut myös asentamaan riippuvuudet manuaalisesti ja luomaan virtuaaliympäristön eli venvin. Jos käytät PyCharmia, nämä hoituvat parilla klikkauksella (PyCharm ehdottaa projektin lataamisen yhteydessä)
    • # Asenna käytetyt kirjastot
      cd bobweb2
      pip install -r requirements.txt
  5. Luo https://t.me/botfather avulla uusi botti ja kopioi botin token talteen. Vaihtoehtoisesti pyydä toisen kehittäjän kehitysbotin tunnukset lainaan.
  6. Lisää tarvittavat ympäristömuuttujat. Ympäristömuuttujia käytetään sellaisten tunnusten välittämiseen, mitä ei voida tallentaa versionhallintaa. Botin käyttämät ympäristömuuttujat löytyvät bobweb/bob/config.py. Ympäristömuuttujan voi lisätä myös main.py ajokonfiguraatioon jos ajat bottia paikallisesti. Dockeria käytettäessä tunnukset pitää olla lisättynä ympäristömuuttujiin
    • Pakollinen ympäristömuuttuja: BOT_TOKEN = Tähän asetettava jonkin BotFatherilla luodun botin tunnus. Muut ympäristömuuttujat ovat tarpeen vain osaan ominaisuuksia
    • Windowsilla ympäristömuuttujan voi asettaa pysyvästi komennolla setx {AVAIN} "{arvo}", missä {AVAIN} on ympäristömuuttujan avain ja {arvo} on sen arvo. Esim botin tokenin voi lisätä windowsin komentoriviltä setx BOT_TOKEN 123ASD456FGH, joss jälkimmäinen merkkijono on todellinen tokeni
    • Linuxille löytyy ohjeet tämän linkin takaa
  7. Luo db.sqlite3 tietokanta komennolla:
    • python bobweb/web/manage.py migrate

Ajaminen paikallisesti ilman Dockeria

  1. Etsi bobweb/bob/main.py ja sen sisältä rivi, joka sisältää if __name__ == '__main__':. Klikkaa sen vasemmalla puolella marginaalissa olevaa nuolta (jos Pycharm) tai ajamalla komentoriviltä python bobweb/bob/main.py komennolla

Ajaminen Docker-kontissa

  1. Asenna lisäksi Docker ja tee asennuksen jälkeiset toimenpiteet niin, että voi ajaa ilman sudo-oikeuksia (linux)
  2. Mikäli Docker (tai Docker Desktop jos windows) on asennettuna (ja käynnissä), ja aiemmat vaiheet on suoritettu, voi konttiin liittyvän imagen buildauksen ja käynnistyksen aloittaa komennolla ./deploy.dev.sh (linux) tai .\deploy.dev.bat (windows). Ensimmäinen imagen build kestää joitakin minuutteja, jonka jälkeen myöhemmät buildit ovat nopeampia.

Yksikkötestien ajaminen

Jos haluat ajaa botin testejä paikallisesti komentoriviltä, onnistuu se alla olevilla komennoilla. Jos käytössäsi on PyCharm Ultimate, ja olet määritellyt testiajajaksi Djangon oman testiajurin (kts. alempaa "PyCharm Ultimate version suositellut asetukset") voit ajaa testejä myös suoraan PyCharmin käyttöliittymästä valitsemalla ajokonfiguraatioksi jonkin testiajon tai klikkaamalla editorin marginaalissa testiluokan/-metodin vieressä olevaa nuolta.

Community Editionilla testejä ajettaessa on käytössä Pythonin oletus testiajaja, jolloin paikalliseen tietokantaan voi jäädä testiajoissa luotua dataa. Community Editionillakin voi ajaa testejä suoraan editorin marginaalista. Tätä varten kannattaa projektiin määritellä ajokonfiguraatio template python-testeille niin, että niissä käytetään oikeaa working directorya. Ohjeet alempana.

Kaikki testit voi ajaa Djangon ajurilla komentoiriviltä alla olevilla komennoilla ja tämä on suositeltavaa aina kun haluaa varmistaa, ettei paikalliset tai kehityshaarassa olevat muutokset ole rikkoneet miään. Testikomentoon voi antaa lisäparametreja, joilla voi tarkentaa mitä testejä ajetaan. Lisätietoa parametreista löytyy Djangon dokumentaatiosta.

# Botin testit
python bobweb/web/manage.py test bobweb/bob

# Webbisivun testit
python bobweb/web/manage.py test bobweb/web

Muutoksia tietokantaan

Tietokanta on Djangon hallinnoima. Näin ollen tietokannan ylläpitoon pätee Djangon perus workflow, joka on dokumentoitu täällä tarkemmin: https://docs.djangoproject.com/en/4.0/topics/migrations

Aina kun tietomalliin tulee muutoksia, eli esim. tietokantaan tulee lisää sarakkeita, sarakkeita poistuu tai sarakkeen nimi muuttuu, tulee tietokanta "migroida". Alta löytyy komentorivikomennot tämän toimenpiteen tekemiseksi.

# Luo migraatiotiedostot
python bobweb/web/manage.py makemigrations

# Lisää migraatiotiedostot versionhallintaan
git add .

# Migroi paikallinen tietokanta
python bobweb/web/manage.py migrate

Jos huomaat puutteita migraatiossa tai teet lisää muutoksia tietomalliin, on mielekästä lopuksi tiivistää kaikki samaan kokonaisuuteen liittyvät muutokset yhteen migraatioon, ettei jokaiselle pienelle muutokselle tule turhaan omaa migraatiotansa. Migraatioiden tiivistäminen onnistuu poistamalla kaikkia kehityshaarassa lisätyt migraatiotiedostot migraatio-kansiosta ja ajamalla komento

# Migratoi paikallisen kannan taaksepäin aiempaan versioon
python bobweb/web/manage.py migrate bobapp XXXX
# missä XXXX on viimeisin migraatio ennen nykyisiä muutoksia.
# Tämän jälkeen kun ajaa jälleen
python bobweb/web/manage.py makemigrations
python bobweb/web/manage.py migrate
# Niin luodaan 1 migraatio kaikille muutoksille ja tietokanta migratoidaan jälleen siihen versioon.
# HUOM! Migraatioissa kulkeminen taaksepäin voi aiheuttaa tiedon menetystä paikallisessa tietokannassa.
# Esim jos olet luonut uuden taulun ja lisännyt sinne jo tietoa, lisäämis-migraation poistaminen
# ja uudelleenluominen aiheuttaa kyseisen taulun sisällön katoamisen

Muutoksia riippuvuuksiin

Jos teit muutoksia esimerkiksi Dockerfile-tiedostoon, voit vielä varmistaa muutostesi toimivuuden paikallisesti alla olevalla komennolla. Tietokoneesi arkkitehtuuri (x86_64) poikkeaa Raspberry Pi:n arkkitehtuurista (armv7l) mikä vaikuttaa riippuvuuksien asentamiseen.

docker build --platform linux/armhf . -t bob-armhf --progress=plain --no-cache

Uuden komennon luominen

Luo uusi moduuli ja sinne luokka joka perii ChatCommand luokan. Esim moduuli (tiedosto) uusi_komento_command.py ja siellä luokka:

class UusiKomento(ChatCommand):
    def __init__(self):
        super().__init__(
            name='uusiKomento',
            regex=regex_simple_command('uusiKomento'),
            help_text_short=('uusiKomento', 'tähän pari sanaa enemmän')
        )

    def is_enabled_in(self, chat):
        return True  # Tähän ehto, että komento on käytössä kyseisessä chatissä.

    async def handle_update(self, update: Update, context: CallbackContext = None):
        # tähän komennon varsinainen toteutus, eli kaikki mitä tapahtuu kun komento laukeaa
        await update.message.reply_text('Hei, tämä on uusi komento')

Tämän jälkeen lisää komento moduulin command_service.py metodiin create_all_but_help_command(). Tämän jälkeen komento on käytettävissä normaalisti.

PyCharm Community Edition suositellut asetukset

Ajokonfiguraatioiden muokkausikkunassa on vasemmassa alakulmassa Edit configuration templates... joka avaa uuden ikkunan mistä pystyy muokkaamaan projektin ajoasetusten oletusarvoja. Nämä oletusarvot tulevat aina jatkossa niille ajokonfiguraatioille, jotka luodaan lennosta kun editorin marginaalista tai kontekstivalikosta valitseee Run..-toiminnon. Aseta Python tests alla olevaan pytest configuraatioon working directory arvoksi projektin juurikansio ("bobweb2"). Tällöin testit mitkä lukevat testiä varten tiedostoja levyltä löytävät ne, eivätkä testit epäonnistu sen takia, että niitä ajetaan väärästä tiedostopolusta.

PyCharm Ultimate version suositellut asetukset

Käy asettamassa PyCharmiin Django-asetukset. Ne löydät asetukset-valikosta polusta Languages & Frameworkds > Django. Aseta seuraavasti:

Asetus Selite
Enable Django Support ☑ (valittu)
Django project root Tähän polku projektin juuri-kansioon (bobweb2-kansio)
Settings Tähän polku settings.py moduuliin, eli bobweb\web\web\settings.py
Do not use Django test runner ☐ (tyhjä)
Manage script Polku manage.py moduuliin, eli bobweb\web\manage.py

Näiden asettamisen jälkeen samassa ikkunassa olevasta napista Show Structure pitäisi aueta pieni ali-ikkuna, jossa näkyy mm. kohdan applications alla kohta bobweb.web.bobapp.

Nämä asetukset mahdollistavat monen toimenpiteen ajamisen ilman komentoriviä suoraan PyCharmin käyttöliittymän kautta. Esim testi-moduulissa yksittäisen testitapauksen voi ajaa marginaalissa sen otsikon vieressä olevasta nuolesta niin, että PyCharm osaa käyttää Djangon testien ajajaa.