Implantação no PythonAnywhere do GitHub



Todos podem fazer isso:


projeto local -> github


Com acesso ssh (pago), você pode fazer o seguinte:


projeto local -> PythonAnywhere


O artigo mostra como (de graça) fazer isso:


projeto local -> github -> PythonAnywhere


Primeiro, vou listar por que você pode precisar disso e depois passar para como implementá-lo. Sinta-se livre para pular o artigo se a primeira parte não for interessante para você.




Porque


PythonAnywhere é um ótimo serviço! É gratuito, fornece boa energia e até um banco de dados, para que você possa criar um site dinâmico em alguns minutos. Essa é uma ótima opção para iniciantes que desejam experimentar algo ao vivo e para aqueles que precisam hospedar uma API ou algum projeto pessoal.


Mas o serviço também tem desvantagens. E se você deseja abrir o código em que está trabalhando? Você apoiará e fará alterações em dois lugares ao mesmo tempo? Uma vez na produção do PythonAnywhere e uma segunda vez no GitHub para outros desenvolvedores. E se você aceitar solicitação de recebimento ou desejar integrar o IC? Duplicar constantemente todas as ações é muito inconveniente.


O GitHub é um ótimo serviço para trabalhar juntos e visualizar o código-fonte, a interface do usuário é melhor do que no PythonAnywhere e, para o que estou levando, editar o código diretamente no PythonAnywhere não é muito agradável. E se pudéssemos combinar o melhor dos dois mundos?


Você envia todas as atualizações no GitHub, e o aplicativo PythonAnywhere é sincronizado e reiniciado automaticamente. Você pode piscar PRs, usar tickets, visualizar seu código em qualquer dispositivo sem precisar fazer login e sem abrir um arquivo no editor de código - em geral, fazendo tudo o que o GitHub permite.


Já ouço um murmúrio: "Bom, bom, convencido, mas como isso pode ser alcançado?" Nem uma palavra mais!




Como


Usamos os webhooks do Github para notificá-lo sobre uma atualização do aplicativo, puxá-lo e recarregá-lo.


Como exemplo, considerarei meu aplicativo SwagLyrics , cujo backend eu possuo no PythonAnywhere. Como estou usando o Flask, o processo será diferente para outra estrutura.


Primeiro, sincronize o projeto para que o GitHub seja de origem. Se você ainda não criou um repositório PythonAnywhere, é possível inicializá-lo ou codificá-lo diretamente no GitHub.


Algo como:


git init git remote add origin https://github.com/yourusername/yourreponame.git 

Agora vá para GitHub -> Configurações -> Webhooks -> Adicionar webhook


Lá você verá:



No campo "URL da carga útil", adicione seu_domínio / route_to_update


Por exemplo, o webhook do meu repositório aponta para nbsp; https://aadibajpai.pythonanywhere.com/update_server


Altere o "Tipo de conteúdo" de application / x-www-form-urlencoded para application / json (eu vou lhe dizer por que isso é necessário um pouco mais tarde).


Ainda não vamos tocar no campo secreto.


Verifique se a opção "push event" está selecionada e clique em "Add webhook".


Abra seu aplicativo no Flask, configuraremos uma rota para receber informações do GitHub quando ocorrer um evento push. O caminho deve ser o especificado no campo "URL da carga útil". Não especificamos explicitamente o ramo mestre, como por simplicidade, está implícito que é o único no repositório.


A configuração mais simples seria assim:


 from flask import Flask, request import git 

 app = Flask(__name__) 

 @app.route('/update_server', methods=['POST']) def webhook(): if request.method == 'POST': repo = git.Repo('path/to/git_repo') origin = repo.remotes.origin 

  origin.pull() 

  return 'Updated PythonAnywhere successfully', 200 else: return 'Wrong event type', 400 

Este é o exemplo mais trivial, uma versão mais completa será menor.


Agora, sempre que ocorrer um evento push, o aplicativo se atualizará fazendo pull.


Se tudo correu bem, eis o que você verá após o próximo commit:



Antes de prosseguirmos para proteger o webhook de estranhos, vou lhe dizer como reiniciar o aplicativo após o pull, para que você não precise fazer isso manualmente.


Recarga automática de aplicativo da Web


Vamos usar ganchos git. Estes são apenas comandos shell executados após os eventos. Não há gancho para o evento após o pull, mas ...


Usamos o fato de que git pull nada mais é do que git fetchgit merge , mas existe um gancho para o evento após a mesclagem . É executado se a solicitação for concluída com êxito.


No seu repositório PythonAnywhere, vá para .git / hooks /


Já haverá vários ganchos existentes, adicione seus próprios criando um arquivo pós-mesclagem


Escreva o seguinte código nele:


 #!/bin/sh touch /path/to/username_pythonanywhere_com_wsgi.py 

Use o caminho para o seu wsgi, que, quando alterado (toque), reinicia o aplicativo.


Para tornar o arquivo executável, abra o console e execute


 chmod +x post-merge 

Verifique se a reinicialização funciona executando uma nova confirmação.


Agora vamos passar a proteger um webhook.




Proteção Webhook


É necessário proteger um webhook para que alguém não possa enviar constantemente solicitações para reiniciar o aplicativo. Vamos usar este guia.


Primeiro, adicione um token secreto no PythonAnywhere como uma variável de ambiente, bem como no campo "Segredo" nas configurações de webhook do GitHub. Aqui, o processo é descrito em mais detalhes.


O GitHub fornece seus métodos em Ruby, mas usamos Python, portanto, usaremos esta função de comparação:


 import hmac import hashlib def is_valid_signature(x_hub_signature, data, private_key): # x_hub_signature and data are from the webhook payload # private key is your webhook secret hash_algorithm, github_signature = x_hub_signature.split('=', 1) algorithm = hashlib.__dict__.get(hash_algorithm) encoded_key = bytes(private_key, 'latin-1') mac = hmac.new(encoded_key, msg=data, digestmod=algorithm) return hmac.compare_digest(mac.hexdigest(), github_signature) 

Agora modifique o controlador update_server para verificar se a assinatura é válida adicionando estas linhas antes da parte da atualização de código:


 x_hub_signature = request.headers.get('X-Hub-Signature') if not is_valid_signature(x_hub_signature, request.data, w_secret): 

w_secret deve corresponder ao valor que você definiu um pouco antes como variável de ambiente.


Em geral, faz sentido adicionar log e mais algumas verificações para garantir que o webhook do GitHub ou que o evento contenha dados; portanto, se desejar, você pode copiar o código relevante do meu repositório , alterando-o sempre que necessário, pois você já sabe tudo o importante


Espero que a informação tenha sido útil. Sei que há muitas coisas, mas queria que você entendesse o que estava acontecendo.




Eu não criei tudo sozinho, reuni o mais importante de várias fontes e criei uma solução completa.


Aqui estão os links que me ajudaram e podem ajudá-lo:
  1. https://stackoverflow.com/a/54268132/9044659 (configuração básica)
  2. https://developer.github.com/webhooks/ (documentação do GitHub webhook)
  3. https://github.com/CCExtractor/sample-platform/blob/master/mod_deploy/controllers.py (uma implementação muito detalhada com várias verificações, se você quiser dedicar algum tempo a isso)
  4. https://github.com/SwagLyrics/swaglyrics-issue-maker/blob/35d23d0ba416e742e381da931d592ce6f58fc13f/issue_maker.py#L268 (implementação do meu controlador para PythonAnywhere)
  5. https://github.com/SwagLyrics/SwagLyrics-For-Spotify (repositório onde eu uso isso na prática)

Obrigado pela leitura!

Source: https://habr.com/ru/post/pt457348/


All Articles