Skip to content

Commit

Permalink
ci: Generate static content for demo index at deploy time
Browse files Browse the repository at this point in the history
Rather than runtime-querying of appengine versions within the
appengine environment, we can instead generate the index at deployment
time (from git tags) and just serve static content.  This simplifies
the system and avoids dependence on Google Cloud.

This was less feasible before we adopted GitHub Actions, but is now
relatively simple.  The index will be regenerated when the index code
is updated or when a new release is created.

Closes shaka-project#4074
  • Loading branch information
joeyparrish committed Apr 12, 2022
1 parent ac5acc8 commit 141a491
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 44 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/demo-version-index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ on:
paths:
- .github/workflows/demo-version-index.yaml
- app-engine/demo-version-index/**
release:
types: [published]

jobs:
appspot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Generate static content
run: python3 app-engine/demo-version-index/generate.py

- uses: google-github-actions/auth@v0
with:
credentials_json: '${{ secrets.APPENGINE_DEPLOY_KEY }}'
Expand Down
1 change: 1 addition & 0 deletions app-engine/demo-version-index/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static/
6 changes: 3 additions & 3 deletions app-engine/demo-version-index/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ releases and demos at https://index-dot-shaka-player-demo.appspot.com/

- app.yaml: App Engine config file. Defines the runtime (Python 3).

- main.py: A python service that queries available versions and generates the
index from a template.
- generate.py: A python script that generates the index's static content from
a template.

- requirements.txt: Used by App Engine to install the necessary Python server
requirements (Flask, App Engine API).
requirements (Flask).

- templates/index.html: A Jinja2 template used to generate the index HTML.
22 changes: 21 additions & 1 deletion app-engine/demo-version-index/app.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
# Copyright 2016 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

runtime: python39
default_expiration: 1s
default_expiration: 1h

# Serve the static/ folder directly.
- url: /(.+)
secure: always
static_files: static/\1
upload: static/.+
80 changes: 41 additions & 39 deletions app-engine/demo-version-index/main.py → app-engine/demo-version-index/generate.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# Shaka Player Version Index - Appspot Entrypoint
#!/usr/bin/env python3

# Shaka Player Version Index Generator
# Copyright 2022 Google LLC
# SPDX-License-Identifier: Apache-2.0

# Generate an index of Shaka Player versions on appspot.

import collections
import google.appengine.api.modules
import jinja2
import os
import random
import re

from flask import Flask, render_template
import subprocess

DEMO_URL_TEMPLATE = 'https://{0}-dot-shaka-player-demo.appspot.com/'

Expand Down Expand Up @@ -90,13 +89,20 @@ def version_to_metadata(v):
'ui_lib_defs': version_to_ui_lib_defs_url(v),
}

def is_release_version(name):
return re.match(r'v\d+-\d+-\d+(?:-.+)?', name)

def appengine_version_to_package_version(version):
# Replace the first two dashes with dots. More dashes indicate a prerelease
# version, as seen in "v2.0.0-beta3".
return version.replace('-', '.', 2)
def is_release_tag(name):
matches = re.match(r'v\d+\.\d+\.\d+(-.+)?', name)
# Doesn't match, not a version tag.
if not matches:
return False
# A "master" (old) or "main" (new) tag, indicating the state of the main
# branch at the time of a release. Not an actual version in itself, though.
if matches.group(1) == '-master' or matches.group(1) == '-main':
return False
# For historical reasons, these oldest few tags are not currently deployed to
# appengine. All other matching tags are, though.
if name in ['v1.2.0', 'v1.2.1', 'v1.2.2', 'v1.2.3']:
return False
return True

def version_key(version):
if version == 'nightly':
Expand All @@ -111,32 +117,13 @@ def version_key(version):
version_tuple = [int(x) for x in main_version.split('.')]
return version_tuple + [suffix]

def get_appengine_versions():
if os.getenv('GAE_ENV', '').startswith('standard'):
# NOTE: this doesn't return anything useful in a local dev server.
return google.appengine.api.modules.modules.get_versions()

# For a local dev server, fake it so we can test sorting.
fake_versions = [
'v1-6-0', 'v1-6-1', 'v1-6-2', 'v1-6-3', 'v1-6-4', 'v1-6-5',
'v2-0-0-beta', 'v2-0-0-beta2', 'v2-0-0-beta3', 'v2-0-0',
'v2-1-0', 'v2-1-1', 'v2-1-2',
'v2-2-1', 'v2-2-2-beta', 'v2-2-2-beta2', 'v2-2-2', 'v2-2-9', 'v2-2-10',
]
random.shuffle(fake_versions) # in-place shuffle
return fake_versions


app = Flask(__name__)
def get_release_tags():
output = subprocess.check_output(['git', 'tag'], text=True)
return list(filter(is_release_tag, output.split('\n')))

@app.route('/')
def root():
appengine_versions = get_appengine_versions()
# Filter for release versions only.
appengine_versions = filter(is_release_version, appengine_versions)

# Now convert from appengine versions (v2-0-0) to package versions (v2.0.0).
versions = list(map(appengine_version_to_package_version, appengine_versions))
def generate():
# Get all release tags.
versions = get_release_tags()
# Now sort, putting prerelease versions ahead of the corresponding release.
versions.sort(key=version_key)

Expand All @@ -158,5 +145,20 @@ def root():
version_metadata['nightly'] = version_to_metadata('nightly')
version_metadata['nightly']['best'] = True

for i in version_metadata.values(): print(i)
return render_template('index.html', versions=version_metadata.values())
# Debug: uncomment to see a list of version metadata objects.
#for i in version_metadata.values(): print(i)

script_path = os.path.dirname(__file__)
template_path = os.path.join(script_path, 'templates', 'index.html')
output_path = os.path.join(script_path, 'static', 'index.html')

os.makedirs(os.path.dirname(output_path), exist_ok=True)

with open(template_path, 'r') as template_file:
with open(output_path, 'w') as output_file:
template = jinja2.Template(template_file.read())
output = template.render(versions=version_metadata.values())
output_file.write(output)

if __name__ == '__main__':
generate()
1 change: 0 additions & 1 deletion app-engine/demo-version-index/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@
# SPDX-License-Identifier: Apache-2.0

Flask==2.0.3
appengine-python-standard==0.3.1

0 comments on commit 141a491

Please sign in to comment.