From 0936c003e8c80c62f64139d888dc4a88b2d66220 Mon Sep 17 00:00:00 2001 From: Oliver Ni Date: Sat, 16 Sep 2023 05:22:46 -0700 Subject: [PATCH] Add continuous deployment job --- .github/workflows/test.yaml | 47 ------------- .github/workflows/test_and_deploy.yaml | 95 ++++++++++++++++++++++++++ config/deploy/prod.json | 1 - fabfile.py | 22 +++--- 4 files changed, 107 insertions(+), 58 deletions(-) delete mode 100644 .github/workflows/test.yaml create mode 100644 .github/workflows/test_and_deploy.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 0d3e8dee..00000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,47 +0,0 @@ -name: Run tests - -on: - push: - branches: - - "*" - pull_request: - branches: ["master"] - -env: - HKNWEB_MODE: dev - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - uses: snok/install-poetry@v1 - with: - version: 1.6.1 - virtualenvs-create: true - virtualenvs-in-project: true - - uses: actions/cache@v3 - with: - path: .venv - key: venv-${{ hashFiles('poetry.lock') }} - - - run: poetry install --no-interaction --no-root - - - name: Run formatting check - run: poetry run black . --check - - - name: Run unit tests - run: | - poetry run coverage run - poetry run coverage report - - - name: Deploy - run: | - poetry run fab deploy - - - name: Run end-to-end tests - run: | - poetry run curl -f localhost:8000 diff --git a/.github/workflows/test_and_deploy.yaml b/.github/workflows/test_and_deploy.yaml new file mode 100644 index 00000000..87c40c6e --- /dev/null +++ b/.github/workflows/test_and_deploy.yaml @@ -0,0 +1,95 @@ +name: Test ๐Ÿงช and deploy ๐Ÿš€ + +on: + push: + branches: + - "*" + pull_request: + branches: ["master"] + +jobs: + test: + runs-on: ubuntu-latest + env: + HKNWEB_MODE: dev + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.9" + - uses: snok/install-poetry@v1 + with: + version: 1.6.1 + virtualenvs-create: true + virtualenvs-in-project: true + - uses: actions/cache@v3 + with: + path: .venv + key: venv-${{ hashFiles('poetry.lock') }} + + - run: poetry install --no-interaction --no-root + + - name: Run formatting check + run: poetry run black . --check + + - name: Run unit tests + run: | + poetry run coverage run + poetry run coverage report + + - name: Deploy + run: | + poetry run fab deploy + + - name: Run end-to-end tests + run: | + poetry run curl -f localhost:8000 + + deploy: + needs: test + runs-on: ubuntu-latest + if: success() && github.ref == 'refs/heads/master' + environment: + name: Production + url: https://dev-hkn.eecs.berkeley.edu/ + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: "3.9" + - uses: snok/install-poetry@v1 + with: + version: 1.6.1 + virtualenvs-create: true + virtualenvs-in-project: true + - uses: actions/cache@v3 + with: + path: .venv + key: venv-${{ hashFiles('poetry.lock') }} + + - run: poetry install --no-interaction --no-root + + - name: Unseal secrets + uses: jrmcdonald/blackbox-github-actions@v0.2.0 + with: + bb_actions_subcommand: "postdeploy" + env: + BLACKBOX_PUBKEY: ${{ secrets.BLACKBOX_PUBLIC_KEY }} + BLACKBOX_PRIVKEY: ${{ secrets.BLACKBOX_PRIVATE_KEY }} + + - name: Setup SSH key + run: | + mkdir -p ~/.ssh/ + echo "$SSH_PRIVATE_KEY" > ~/.ssh/pkey + sudo chmod 600 ~/.ssh/pkey + echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts + shell: bash + env: + SSH_PRIVATE_KEY: ${{ secrets.OCF_SSH_KEY }} + SSH_KNOWN_HOSTS: ${{ secrets.OCF_SSH_KNOWN_HOSTS }} + + - name: Deploy + run: | + poetry run fab deploy -i ~/.ssh/pkey --revision ${{ github.sha }} + env: + HKNWEB_MODE: ${{ vars.HKNWEB_MODE }} diff --git a/config/deploy/prod.json b/config/deploy/prod.json index e3d59268..cb3d9786 100644 --- a/config/deploy/prod.json +++ b/config/deploy/prod.json @@ -1,6 +1,5 @@ { "deploy": { - "branch": "modernization", "name": "prod", "user": "hkn", "host": "apphost.ocf.berkeley.edu", diff --git a/fabfile.py b/fabfile.py index 836f20d3..2f2d36c0 100644 --- a/fabfile.py +++ b/fabfile.py @@ -26,7 +26,7 @@ def global_defaults(): return merge_dicts(Config.global_defaults(), hkn_shared) -def setup(c: Connection, commit=None, release=None): +def setup(c: Connection, revision=None, release=None): print("== Setup ==") # Returns the server date-time, encoded as YYYYMMSS_HHMMSS. @@ -34,9 +34,9 @@ def setup(c: Connection, commit=None, release=None): # Point the connection to the correct git config c.release = release if release else timestamp - c.commit = commit if commit else c.deploy.branch + c.revision = revision if revision else c.deploy.branch print(f"release: {c.release}") - print(f"commit: {c.commit}") + print(f"revision: {c.revision}") # Setup paths c.deploy_path = posixpath.join(c.deploy.path.root, c.deploy.name) @@ -65,7 +65,7 @@ def update(c: Connection): c.deploy.repo_url = ( c.run("git config --get remote.origin.url").stdout.strip() + ".git" ) - c.commit = c.run("git rev-parse HEAD").stdout.strip() + c.revision = c.run("git rev-parse HEAD").stdout.strip() c.run(f"git clone --bare {c.deploy.repo_url} {c.repo_path}", echo=True) @@ -76,19 +76,21 @@ def update(c: Connection): with c.cd(c.repo_path): c.run(f"git remote set-url origin {c.deploy.repo_url}", echo=True) c.run("git remote update", echo=True) - c.run(f"git fetch origin {c.commit}:{c.commit}", echo=True) + c.run(f"git fetch origin {c.revision}:{c.revision}", echo=True) else: # clone c.run(f"git clone --bare {c.deploy.repo_url} {c.repo_path}", echo=True) with c.cd(c.repo_path): print("-- Creating git archive for release") - revision = c.commit + revision = c.revision revision_number = c.run( f"git rev-list --max-count=1 {revision} --", echo=True ).stdout.strip() - c.commit = revision_number + c.revision = revision_number - c.run(f"git archive {c.commit} | tar -x -f - -C '{c.release_path}'", echo=True) + c.run( + f"git archive {c.revision} | tar -x -f - -C '{c.release_path}'", echo=True + ) with c.cd(c.release_path): print("-- Symlinking shared files") @@ -137,9 +139,9 @@ def publish(c: Connection) -> None: @task -def deploy(c, target=None, commit=None): +def deploy(c, target=None, revision=None): with Connection(c.deploy.host, user=c.deploy.user, config=c.config) as c: - setup(c, commit=commit) + setup(c, revision=revision) update(c) publish(c)