home / tils / til

Menu
  • GraphQL API

til: github-actions_deploy-live-demo-when-tests-pass.md

This data as json

path topic title url body html shot created created_utc updated updated_utc shot_hash slug
github-actions_deploy-live-demo-when-tests-pass.md github-actions Deploying a live Datasette demo when the tests pass https://github.com/simonw/til/blob/main/github-actions/deploy-live-demo-when-tests-pass.md I've implemented this pattern a bunch of times now - here's the version I've settled on for my [datasette-auth0 plugin](https://github.com/simonw/datasette-auth0) repository. For publishing to Cloud Run, it needs two GitHub Actions secrets to be configured: `GCP_SA_EMAIL` and `GCP_SA_KEY`. See below for publishing to Vercel. In `.github/workflows/test.yml`: ```yaml name: Test on: [push] jobs: test: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.7", "3.8", "3.9", "3.10"] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - uses: actions/cache@v2 name: Configure pip caching with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} restore-keys: | ${{ runner.os }}-pip- - name: Install dependencies run: | pip install -e '.[test]' - name: Run tests run: | pytest deploy_demo: runs-on: ubuntu-latest needs: [test] if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v2 - name: Set up Python 3.10 uses: actions/setup-python@v2 with: python-version: "3.10" cache: pip cache-dependency-path: "**/setup.py" - name: Install datasette run: pip install datasette - name: Set up Cloud Run uses: google-github-actions/setup-gcloud@v0 with: version: '275.0.0' service_account_email: ${{ secrets.GCP_SA_EMAIL }} service_account_key: ${{ secrets.GCP_SA_KEY }} - name: Deploy demo to Cloud Run env: CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }} run: |- gcloud config set run/region us-central1 gcloud config set project datasette-222320 wget https://latest.datasette.io/fixtures.db datasette publish cloudrun fixtures.db \ --install https://github.com/simonw/datasette-auth0/archive/$GITHUB_SHA.zip \ --plugin-secret datasette-auth0 domain "datasette.us.auth0.com" \ --plugin-secret datasette-auth0 client_id "n9eaHS0ckIsujoyZNZ1wVgcPevjAcAXn" \ --plugin-secret datasette-auth0 client_secret "$CLIENT_SECRET" \ --about "datasette-auth0" \ --about_url "https://datasette.io/plugins/datasette-auth0" \ --service datasette-auth0-demo ``` The first job called `test` runs the Python tests in the repo. The second `deploy_demo` block is where things get interesting. ```yaml deploy_demo: runs-on: ubuntu-latest needs: [test] if: github.ref == 'refs/heads/main' ``` The `needs: [test]` bit ensures this only runs if the tests pass first. `if: github.ref == 'refs/heads/main'` causes the deploy to only run on pushes to the `main` branch. The most interesting bit of the deploy command is this bit: ``` datasette publish cloudrun fixtures.db \ --install https://github.com/simonw/datasette-auth0/archive/$GITHUB_SHA.zip \ ... ``` `$GITHUB_SHA` is the commit hash that triggered the wokrflow. The `--install` line there constructs a URL to the zip archive of that version from the GitHub repository - so that exact version will be treated as a plugin and installed as part of deploying the Datasette demo instance. ## Deploying to Vercel [This example](https://github.com/simonw/datasette-hashed-urls/blob/659614c23cbc544915079c44b09b09b090400ff8/.github/workflows/test.yml) deploys to Vercel instead. The key difference is this: ```yaml - name: Install datasette run: pip install datasette datasette-publish-vercel - name: Deploy demo to Vercel env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} run: |- wget https://latest.datasette.io/fixtures.db datasette publish vercel fixtures.db \ --project datasette-hashed-urls \ --install https://github.com/simonw/datasette-hashed-urls/archive/$GITHUB_SHA.zip \ --token $VERCEL_TOKEN \ --scope datasette ``` The `--token $VERCEL_TOKEN` passes a token created in the Vercel dashboard. I needed `--scope datasette` here because I was deploying to a Vercel team of that name - if deploying to your personal account you can leave this off. <p>I've implemented this pattern a bunch of times now - here's the version I've settled on for my <a href="https://github.com/simonw/datasette-auth0">datasette-auth0 plugin</a> repository.</p> <p>For publishing to Cloud Run, it needs two GitHub Actions secrets to be configured: <code>GCP_SA_EMAIL</code> and <code>GCP_SA_KEY</code>.</p> <p>See below for publishing to Vercel.</p> <p>In <code>.github/workflows/test.yml</code>:</p> <div class="highlight highlight-source-yaml"><pre><span class="pl-ent">name</span>: <span class="pl-s">Test</span> <span class="pl-ent">on</span>: <span class="pl-s">[push]</span> <span class="pl-ent">jobs</span>: <span class="pl-ent">test</span>: <span class="pl-ent">runs-on</span>: <span class="pl-s">ubuntu-latest</span> <span class="pl-ent">strategy</span>: <span class="pl-ent">matrix</span>: <span class="pl-ent">python-version</span>: <span class="pl-s">["3.7", "3.8", "3.9", "3.10"]</span> <span class="pl-ent">steps</span>: - <span class="pl-ent">uses</span>: <span class="pl-s">actions/checkout@v2</span> - <span class="pl-ent">name</span>: <span class="pl-s">Set up Python ${{ matrix.python-version }}</span> <span class="pl-ent">uses</span>: <span class="pl-s">actions/setup-python@v2</span> <span class="pl-ent">with</span>: <span class="pl-ent">python-version</span>: <span class="pl-s">${{ matrix.python-version }}</span> - <span class="pl-ent">uses</span>: <span class="pl-s">actions/cache@v2</span> <span class="pl-ent">name</span>: <span class="pl-s">Configure pip caching</span> <span class="pl-ent">with</span>: <span class="pl-ent">path</span>: <span class="pl-s">~/.cache/pip</span> <span class="pl-ent">key</span>: <span class="pl-s">${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}</span> <span class="pl-ent">restore-keys</span>: <span class="pl-s">|</span> <span class="pl-s"> ${{ runner.os }}-pip-</span> <span class="pl-s"></span> - <span class="pl-ent">name</span>: <span class="pl-s">Install dependencies</span> <span class="pl-ent">run</span>: <span class="pl-s">|</span> <span class="pl-s"> pip install -e '.[test]'</span> <span class="pl-s"></span> - <span class="pl-ent">name</span>: <span class="pl-s">Run tests</span> <span class="pl-ent">run</span>: <span class="pl-s">|</span> <span class="pl-s"> pytest</span> <span class="pl-s"></span> <span class="pl-ent">deploy_demo</span>: <span class="pl-ent">runs-on</span>: <span class="pl-s">ubuntu-latest</span> <span class="pl-ent">needs</span>: <span class="pl-s">[test]</span> <span class="pl-ent">if</span>: <span class="pl-s">github.ref == 'refs/heads/main'</span> <span class="pl-ent">steps</span>: - <span class="pl-ent">uses</span>: <span class="pl-s">actions/checkout@v2</span> - <span class="pl-ent">name</span>: <span class="pl-s">Set up Python 3.10</span> <span class="pl-ent">uses</span>: <span class="pl-s">actions/setup-python@v2</span> <span class="pl-ent">with</span>: <span class="pl-ent">python-version</span>: <span class="pl-s"><span class="pl-pds">"</span>3.10<span class="pl-pds">"</span></span> <span class="pl-ent">cache</span>: <span class="pl-s">pip</span> <span class="pl-ent">cache-dependency-path</span>: <span class="pl-s"><span class="pl-pds">"</span>**/setup.py<span class="pl-pds">"</span></span> - <span class="pl-ent">name</span>: <span class="pl-s">Install datasette</span> <span class="pl-ent">run</span>: <span class="pl-s">pip install datasette</span> - <span class="pl-ent">name</span>: <span class="pl-s">Set up Cloud Run</span> <span class="pl-ent">uses</span>: <span class="pl-s">google-github-actions/setup-gcloud@v0</span> <span class="pl-ent">with</span>: <span class="pl-ent">version</span>: <span class="pl-s"><span class="pl-pds">'</span>275.0.0<span class="pl-pds">'</span></span> <span class="pl-ent">service_account_email</span>: <span class="pl-s">${{ secrets.GCP_SA_EMAIL }}</span> <span class="pl-ent">service_account_key</span>: <span class="pl-s">${{ secrets.GCP_SA_KEY }}</span> - <span class="pl-ent">name</span>: <span class="pl-s">Deploy demo to Cloud Run</span> <span class="pl-ent">env</span>: <span class="pl-ent">CLIENT_SECRET</span>: <span class="pl-s">${{ secrets.AUTH0_CLIENT_SECRET }}</span> <span class="pl-ent">run</span>: <span class="pl-s">|-</span> <span class="pl-s"> gcloud config set run/region us-central1</span> <span class="pl-s"> gcloud config set project datasette-222320</span> <span class="pl-s"> wget https://latest.datasette.io/fixtures.db</span> <span class="pl-s"> datasette publish cloudrun fixtures.db \</span> <span class="pl-s"> --install https://github.com/simonw/datasette-auth0/archive/$GITHUB_SHA.zip \</span> <span class="pl-s"> --plugin-secret datasette-auth0 domain "datasette.us.auth0.com" \</span> <span class="pl-s"> --plugin-secret datasette-auth0 client_id "n9eaHS0ckIsujoyZNZ1wVgcPevjAcAXn" \</span> <span class="pl-s"> --plugin-secret datasette-auth0 client_secret "$CLIENT_SECRET" \</span> <span class="pl-s"> --about "datasette-auth0" \</span> <span class="pl-s"> --about_url "https://datasette.io/plugins/datasette-auth0" \</span> <span class="pl-s"> --service datasette-auth0-demo</span></pre></div> <p>The first job called <code>test</code> runs the Python tests in the repo. The second <code>deploy_demo</code> block is where things get interesting.</p> <div class="highlight highlight-source-yaml"><pre> <span class="pl-ent">deploy_demo</span>: <span class="pl-ent">runs-on</span>: <span class="pl-s">ubuntu-latest</span> <span class="pl-ent">needs</span>: <span class="pl-s">[test]</span> <span class="pl-ent">if</span>: <span class="pl-s">github.ref == 'refs/heads/main'</span></pre></div> <p>The <code>needs: [test]</code> bit ensures this only runs if the tests pass first.</p> <p><code>if: github.ref == 'refs/heads/main'</code> causes the deploy to only run on pushes to the <code>main</code> branch.</p> <p>The most interesting bit of the deploy command is this bit:</p> <pre><code>datasette publish cloudrun fixtures.db \ --install https://github.com/simonw/datasette-auth0/archive/$GITHUB_SHA.zip \ ... </code></pre> <p><code>$GITHUB_SHA</code> is the commit hash that triggered the wokrflow. The <code>--install</code> line there constructs a URL to the zip archive of that version from the GitHub repository - so that exact version will be treated as a plugin and installed as part of deploying the Datasette demo instance.</p> <h2> <a id="user-content-deploying-to-vercel" class="anchor" href="#deploying-to-vercel" aria-hidden="true"><span aria-hidden="true" class="octicon octicon-link"></span></a>Deploying to Vercel</h2> <p><a href="https://github.com/simonw/datasette-hashed-urls/blob/659614c23cbc544915079c44b09b09b090400ff8/.github/workflows/test.yml">This example</a> deploys to Vercel instead. The key difference is this:</p> <div class="highlight highlight-source-yaml"><pre> - <span class="pl-ent">name</span>: <span class="pl-s">Install datasette</span> <span class="pl-ent">run</span>: <span class="pl-s">pip install datasette datasette-publish-vercel</span> - <span class="pl-ent">name</span>: <span class="pl-s">Deploy demo to Vercel</span> <span class="pl-ent">env</span>: <span class="pl-ent">VERCEL_TOKEN</span>: <span class="pl-s">${{ secrets.VERCEL_TOKEN }}</span> <span class="pl-ent">run</span>: <span class="pl-s">|-</span> <span class="pl-s"> wget https://latest.datasette.io/fixtures.db</span> <span class="pl-s"> datasette publish vercel fixtures.db \</span> <span class="pl-s"> --project datasette-hashed-urls \</span> <span class="pl-s"> --install https://github.com/simonw/datasette-hashed-urls/archive/$GITHUB_SHA.zip \</span> <span class="pl-s"> --token $VERCEL_TOKEN \</span> <span class="pl-s"> --scope datasette</span></pre></div> <p>The <code>--token $VERCEL_TOKEN</code> passes a token created in the Vercel dashboard. I needed <code>--scope datasette</code> here because I was deploying to a Vercel team of that name - if deploying to your personal account you can leave this off.</p> <Binary: 45,343 bytes> 2022-03-27T20:16:50-07:00 2022-03-28T03:16:50+00:00 2022-03-27T20:16:50-07:00 2022-03-28T03:16:50+00:00 7512db1a0c8703bd517605a7eda793a8 deploy-live-demo-when-tests-pass
Powered by Datasette · How this site works · Code of conduct