Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Github action for continuous deployment to GAM #337

Merged
merged 10 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/workflows/gam.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Deploy Templates to GAM

permissions:
contents: read

concurrency:
group: 'deploy'
cancel-in-progress: true

on:
push:
branches:
- main
workflow_dispatch:

jobs:
lint:
name: Linting
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup node
uses: guardian/actions-setup-node@main

- name: Install dependencies
uses: bahmutov/npm-install@v1

- name: Lint files
run: yarn lint

types:
name: Typescript
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup node
uses: guardian/actions-setup-node@main

- name: Install dependencies
uses: bahmutov/npm-install@v1

- name: Check typescript
run: yarn tsc

deploy:
runs-on: ubuntu-latest
needs: [lint, types]

steps:
- uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'

- name: Install pipenv
run: pip install pipenv

- name: Setup Node
uses: actions/setup-node@v3

- name: Install dependencies
run: yarn install --frozen-lockfile

- name: Build
run: yarn build

- name: Install Dependencies
run: pipenv install
working-directory: ./scripts/deploy

- name: Deploy Templates to GAM
run: pipenv run python deploy.py
working-directory: ./scripts/deploy
env:
GAM_APPLICATION_NAME: ${{ secrets.GAM_APPLICATION_NAME }}
GAM_NETWORK_CODE: ${{ secrets.GAM_NETWORK_CODE }}
SERVICE_ACCOUNT_KEY_FILE: ${{ secrets.SERVICE_ACCOUNT_KEY_FILE }}
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ legacy
/.svelte-kit

# Python
scripts/upload
scripts/deploy
File renamed without changes.
1 change: 0 additions & 1 deletion scripts/upload/Pipfile → scripts/deploy/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@ termcolor = "*"

[requires]
python_version = "3.11"
python_full_version = "3.11.2"
File renamed without changes.
8 changes: 3 additions & 5 deletions scripts/upload/README.md → scripts/deploy/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
# Upload to GAM
# Deploy to GAM
This script will attempt to upload all commercial templates to GAM, replacing the corresponding generated HTML & CSS.

The script checks for the presence of an `ad.json` file in the template directory. This file must contain the key `nativeStyleId`, specifying the ID for the corresponding [native style][native-style] in GAM.

[native-style]: https://support.google.com/admanager/answer/13404315?hl=en&ref_topic=7032550&sjid=6297647672569553146-EU

It's written in python because Google does not offer a JS SDK.

## Requirements
- Python 3.x
- An OAuth2 client id and secret

## Running locally
```bash
$ cd scripts/upload
$ cd scripts/deploy
$ cp .env.example .env # fill this in
$ pipenv install
$ pipenv run python upload.py
$ pipenv run python deploy.py
```
59 changes: 31 additions & 28 deletions scripts/upload/upload.py → scripts/deploy/deploy.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,26 @@
import os
import tempfile
from dotenv import load_dotenv
import json
from googleads import ad_manager, common
from googleads import ad_manager, common, oauth2
import datetime
from termcolor import colored, cprint
from termcolor import cprint

load_dotenv()

template_dir = os.path.realpath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../build-static")
os.path.join(os.path.dirname(os.path.abspath(__file__)),
"../../build-static")
)

config = {
"application_name": os.environ.get("GAM_APPLICATION_NAME"),
"network_code": os.environ.get("GAM_NETWORK_CODE"),
"client_id": os.environ.get("GAM_CLIENT_ID"),
"client_secret": os.environ.get("GAM_CLIENT_SECRET"),
"refresh_token": os.environ.get("GAM_REFRESH_TOKEN"),
"network_code": os.environ.get("GAM_NETWORK_CODE")
}

config_yaml = """
ad_manager:
application_name: {application_name}
network_code: {network_code}
client_id: {client_id}
client_secret: {client_secret}
refresh_token: {refresh_token}
""".format(
**config
)

html_prefix = "<!-- DO NOT EDIT -- FILE GENERATED AND UPLOADED AUTOMATICALLY FROM https://github.com/guardian/commercial-templates ON {} -->".format(
html_prefix = "<!-- DO NOT EDIT -- FILE GENERATED AND DEPLOYED AUTOMATICALLY FROM https://github.com/guardian/commercial-templates ON {} -->".format(
datetime.datetime.now().strftime("%m/%d/%Y")
)
css_prefix = "/* DO NOT EDIT -- FILE GENERATED AND UPLOADED AUTOMATICALLY FROM https://github.com/guardian/commercial-templates ON {} */".format(
css_prefix = "/* DO NOT EDIT -- FILE GENERATED AND DEPLOYED AUTOMATICALLY FROM https://github.com/guardian/commercial-templates ON {} */".format(
datetime.datetime.now().strftime("%m/%d/%Y")
)

Expand Down Expand Up @@ -65,7 +52,8 @@ def upload_template(
version="v202208", where="id = %s" % templateInfo["nativeStyleId"]
)

response = native_style_service.getNativeStylesByStatement(statement.ToStatement())
response = native_style_service.getNativeStylesByStatement(
statement.ToStatement())

if "results" in response and len(response["results"]):
style = response["results"][0]
Expand All @@ -84,7 +72,8 @@ def upload_template(
cprint("[!] Error updating native style: %s" % e, "red")
return

cprint('[✔️] Native style "%s" was updated.' % (style["name"]), "green")
cprint('[✔️] Native style "%s" was updated.' %
(style["name"]), "green")
else:
cprint(
'[i] No native styles found to update for "%s" with nativeStyleId "%s"'
Expand All @@ -100,10 +89,24 @@ def main(native_style_service: common.GoogleSoapService):


if __name__ == "__main__":
ad_manager_client = ad_manager.AdManagerClient.LoadFromString(config_yaml)
key_json = os.environ.get("SERVICE_ACCOUNT_KEY_FILE") or ""

native_style_service = ad_manager_client.GetService(
"NativeStyleService", version="v202305"
)
fd, key_file = tempfile.mkstemp()

try:
with os.fdopen(fd, 'w') as tmp:
tmp.write(key_json)

oauth2_client = oauth2.GoogleServiceAccountClient(
key_file, oauth2.GetAPIScope('ad_manager'))

ad_manager_client = ad_manager.AdManagerClient(
oauth2_client, config['application_name'], config['network_code'])

native_style_service = ad_manager_client.GetService(
"NativeStyleService", version="v202305"
)

main(native_style_service)
main(native_style_service)
finally:
os.remove(key_file)
3 changes: 3 additions & 0 deletions src/templates/csr/public-good/ad.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"nativeStyleId": "756061"
}
3 changes: 3 additions & 0 deletions src/templates/ssr/interscroller/ad.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"nativeStyleId": "290379"
}
Loading