Archived
Watch
0
0
Fork
You've already forked www
0

refacture all the things!

This commit is contained in:
XenGi 2023-06-13 12:47:07 +02:00
commit 2e3a02af0c
Signed by: xengi
SSH key fingerprint: SHA256:EvLbWxFCtfmd+8Xa6RkzkhIga+wFkKCekfFacYVn63M
12 changed files with 169 additions and 153 deletions

113
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,113 @@
name: Release website
on:
push:
branches:
- staging
- production
workflow_dispatch:
jobs:
pages:
runs-on: ubuntu-latest
environment: staging
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
- name: Build pages
run: hugo $(cat .hugo-params)
- uses: actions/upload-artifact@v3
name: Upload pages
with:
name: pages
path: public
calendar:
needs: [ pages ]
runs-on: ubuntu-latest
environment: staging
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive
fetch-depth: 0
- name: Setup Python
uses: actions/setup-python@v4
with:
cache: 'pip' # caching pip dependencies
- name: Install dependencies
run: |
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
- name: Download pages
uses: actions/download-artifact@v3
with:
name: pages
path: "."
- name: Generate calendars
run: python tools/merge_cals.py
- name: Copy calendar to output dir
run: cp static/all.ics public/all.ics
- name: Update homepage with latest event
run: upcoming="$(python tools/gen_upcoming.py static/all.ics 20 5|tr '\n' ' ')" && sed -i "s#CALENDAR#$upcoming#g" public/index.html
- uses: actions/upload-artifact@v3
name: Upload pages
with:
name: enhanced_pages
path: public
staging:
needs: [ calendar ]
runs-on: ubuntu-latest
environment: staging
if: github.ref == 'refs/heads/staging' && github.event_name == 'push'
steps:
- name: Download pages
uses: actions/download-artifact@v3
with:
name: enhanced_pages
path: "."
- name: Generate timestamp
run: echo "timestamp=$(date --iso-8601=seconds)" >> $GITHUB_ENV
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: staging-${{ env.timestamp }}
release_name: Staging release ${{ env.timestamp }}
body: New Website staging version ${{ env.timestamp }}
draft: false
prerelease: false
release:
needs: [ calendar ]
runs-on: ubuntu-latest
environment: production
if: github.ref == 'refs/heads/production' && github.event_name == 'push'
steps:
- name: Download pages
uses: actions/download-artifact@v3
with:
name: enhanced_pages
path: "."
- name: Generate timestamp
run: echo "timestamp=$(date --iso-8601=seconds)" >> $GITHUB_ENV
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: production-${{ env.timestamp }}
release_name: Production release ${{ env.timestamp }}
body: New Website production version ${{ env.timestamp }}
draft: false
prerelease: false

View file

@ -1,42 +1,51 @@
![CCCB logo](static/img/logo.png)
# CCCB Website # CCCB Website
This is the website of CCCB. This is the website of the CCCB.
## Getting started ## Getting started
Get Hugo: <https://gohugo.io/getting-started/installing> 1. Get Hugo: <https://gohugo.io/getting-started/installing>
2. Clone this repo
Clone this repo ```shell
```
git clone https://github.com/cccb/www git clone https://github.com/cccb/www
``` ```
3. Switch directory
Switch directory ```shell
```
cd www cd www
``` ```
3. Fetch Submodules
Fetch Submodules ```shell
```
git submodule update --recursive --remote --init git submodule update --recursive --remote --init
``` ```
### Run site locally ### Run site locally
Run hugo webserver Run hugo webserver:
```
```shell
hugo serve hugo serve
``` ```
Point your browser to http://localhost:1313/
To ready your site for upload, run "./build.sh", which also generates all.ics and adds the calendar table to index.html Point your browser to: http://localhost:1313/
To ready your site for upload, run `./build.sh`, which also generates `all.ics` and adds the calendar table to `index.html`.
Every change you make on the project will be reflected in your browser as long as `hugo serve` is running. Every change you make on the project will be reflected in your browser as long as `hugo serve` is running.
## Making a change ## Making a change
* Use your local dev setup (see Getting started) or via GitLab editor. 1. Use your local dev setup (see Getting started) or via GitHub editor.
* Make your change in `staging` branch. 2. Make your change in `staging` branch.
* Commit (and push) your change. 3. Commit (and push) your change.
* Gitlab CI is running pipeline. If successfull, check [Staging Website](https://staging.berlin.ccc.de/) if change is correct. 4. GitHub Actions is running the release workflow.
* Create merge request to merge changes from `staging` to `production`. Ask somebody to check merge request or if small change, merge yourself. - If successful, check [Staging Website](https://staging.berlin.ccc.de/) if change is correct.
* Gitlab CI is running pipeline. If successfull, check [Website](https://berlin.ccc.de/) if change is correct. 5. Create merge request to merge changes from `staging` to `production` branch. Ask somebody to check merge request or if small change, merge yourself.
6. GitHub Actions is running the release workflow.
- If successfull, check [Website](https://berlin.ccc.de/) if change is correct.
7. Profit!
---
Made with ❤️ and [Hugo](https://gohugo.io).

12
TODO.md
View file

@ -1,15 +1,14 @@
Todo # Todo
----
- DSGVO-compliant Datenschutzerklärung reinbasteln - DSGVO-compliant Datenschutzerklärung reinbasteln
- Entscheiden, welche Seiten sonst noch konvertiert werden sollen und welche in die ewigen Datengründe gehen können - Entscheiden, welche Seiten sonst noch konvertiert werden sollen und welche in die ewigen Datengründe gehen können
Done # Done
----
- Template aussuchen - Template aussuchen
- Rausfinden, wie man eine Seite konvertiert - Rausfinden, wie man eine Seite konvertiert
- hugo new page/mypage.md - `hugo new page/mypage.md`
- pandoc -f mediawiki page.mw -t markdown >> page/mypage.md - `pandoc -f mediawiki page.mw -t markdown >> page/mypage.md`
- Wichtigste Seiten konvertieren - Wichtigste Seiten konvertieren
- Membership-Seite auf den aktuellen Stand der Wahrheit bringen - Membership-Seite auf den aktuellen Stand der Wahrheit bringen
- Ical template bauen - Ical template bauen
@ -17,3 +16,4 @@ Done
- Bestehende Datengarten-Termine konvertieren - Bestehende Datengarten-Termine konvertieren
- ggf. template mit frontmatter - ggf. template mit frontmatter
- Theme forken, alle assets sollten lokal gehosted sein und nicht von irgendwelchen CDNs bezogen werden (HTTP/2 ftw!) - Theme forken, alle assets sollten lokal gehosted sein und nicht von irgendwelchen CDNs bezogen werden (HTTP/2 ftw!)

View file

@ -1,7 +1,8 @@
#!/usr/bin/env sh #!/bin/sh
hugo $(cat .hugo-params) hugo $(cat .hugo-params)
tools/merge_cals.py ./tools/merge_cals.py
upcoming="$(tools/gen_upcoming.py static/all.ics 20 5 | tr '\n' ' ')" upcoming="$(tools/gen_upcoming.py static/all.ics 20 5 | tr '\n' ' ')"
cp static/all.ics public/all.ics cp static/all.ics public/all.ics
sed -i "s#CALENDAR#$upcoming#g" public/index.html sed -i "s#CALENDAR#$upcoming#g" public/index.html

View file

@ -63,7 +63,6 @@ mediaTypes:
suffixes: suffixes:
- "xml" - "xml"
outputFormats: outputFormats:
RSS: RSS:
mediaType: "application/rss" mediaType: "application/rss"
@ -80,3 +79,4 @@ outputs:
page: page:
- "HTML" - "HTML"
- "Calendar" - "Calendar"

View file

@ -11,7 +11,7 @@
{{ range .Params.tags }} {{ range .Params.tags }}
<a href="{{ $.Site.LanguagePrefix | absURL }}/tags/{{ . | urlize }}/">{{ . }}</a>&nbsp; <a href="{{ $.Site.LanguagePrefix | absURL }}/tags/{{ . | urlize }}/">{{ . }}</a>&nbsp;
{{ end }} {{ end }}
</div> </div><!--/.blog-tags-->
{{ end }} {{ end }}
{{ if .Site.Params.socialShare }} {{ if .Site.Params.socialShare }}
@ -19,24 +19,24 @@
<section id="social-share"> <section id="social-share">
<ul class="list-inline footer-links"> <ul class="list-inline footer-links">
{{ partial "share-links" . }} {{ partial "share-links" . }}
</ul> </ul><!--/.social-share-->
</section> </section><!--/.list-inline /.footer-links-->
{{ end }} {{ end }}
</article> </article><!--/.blog-post-->
{{ if ne .Type "page" }} {{ if ne .Type "page" }}
<ul class="pager blog-pager"> <ul class="pager blog-pager">
{{ if .PrevInSection }} {{ if .PrevInSection }}
<li class="previous"> <li class="previous">
<a href="{{ .PrevInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .PrevInSection.Title }}">&larr; {{ i18n "previousPost" }}</a> <a href="{{ .PrevInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .PrevInSection.Title }}">&larr; {{ i18n "previousPost" }}</a>
</li> </li><!--/.previous-->
{{ end }} {{ end }}
{{ if .NextInSection }} {{ if .NextInSection }}
<li class="next"> <li class="next">
<a href="{{ .NextInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .NextInSection.Title }}">{{ i18n "nextPost" }} &rarr;</a> <a href="{{ .NextInSection.Permalink }}" data-toggle="tooltip" data-placement="top" title="{{ .NextInSection.Title }}">{{ i18n "nextPost" }} &rarr;</a>
</li> </li><!--/.next-->
{{ end }} {{ end }}
</ul> </ul><!--/.pager /.blog-pager-->
{{ end }} {{ end }}
@ -44,16 +44,16 @@
{{ if .Site.DisqusShortname }} {{ if .Site.DisqusShortname }}
<div class="disqus-comments"> <div class="disqus-comments">
{{ template "_internal/disqus.html" . }} {{ template "_internal/disqus.html" . }}
</div> </div><!--/.disqus-comments-->
{{ end }} {{ end }}
{{ if .Site.Params.staticman }} {{ if .Site.Params.staticman }}
<div class="staticman-comments"> <div class="staticman-comments">
{{ partial "staticman-comments.html" . }} {{ partial "staticman-comments.html" . }}
</div> </div><!--/.staticman-comments-->
{{ end }} {{ end }}
{{ end }} {{ end }}
</div> </div><!--/.col-lg-8 /.col-lg-offset-2 /.col-md-10 /.col-md-offset-1-->
</div> </div><!--/.row-->
</div> </div><!--/.container-->
{{ end }} {{ end }}

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
if [ $# -lt 2 ]; then if [ $# -lt 2 ]; then
echo "Usage: $0 Mediawiki_Page_Name [page|post]" echo "Usage: $0 Mediawiki_Page_Name [page|post]"
@ -10,6 +10,9 @@ echo Converting $1...
page=$(echo $1 | sed 's,/,_,g' | tr '[:upper:]' '[:lower:]') page=$(echo $1 | sed 's,/,_,g' | tr '[:upper:]' '[:lower:]')
hugo new $2/$page.md hugo new $2/$page.md
curl -s https://berlin.ccc.de/api.php\?action\=query\&prop\=revisions\&rvprop\=content\&format\=json\&titles\=$1 | \ curl -s "https://berlin.ccc.de/api.php?action=query&prop=revisions&rvprop=content&format=json&titles=$1" \
jq -r '.query.pages |..| objects|.["*"]'| sed '/null/d' | pandoc -f mediawiki -t markdown \ | jq -r '.query.pages |..| objects|.["*"]' \
| sed '/null/d' \
| pandoc -f mediawiki -t markdown \
>> content/$2/$page.md >> content/$2/$page.md

View file

@ -3,7 +3,6 @@
import sys import sys
import logging import logging
import locale import locale
from pprint import pprint
from dateutil.parser import parse from dateutil.parser import parse
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dateutil.rrule import rruleset, rrulestr from dateutil.rrule import rruleset, rrulestr
@ -13,71 +12,74 @@ import icalendar
def vevent_to_event(event, rrstart=None): def vevent_to_event(event, rrstart=None):
if rrstart == None: if rrstart == None:
begin = parse(event['DTSTART'].to_ical()) begin = parse(event["DTSTART"].to_ical())
else: else:
begin = rrstart begin = rrstart
return { "name": event['SUMMARY'].to_ical(), "url": event['URL'].to_ical(), "begin": begin }
return {
"name": event["SUMMARY"].to_ical(),
"url": event["URL"].to_ical(),
"begin": begin
}
def parse_single_event(event, start, end): def parse_single_event(event, start, end):
logging.info("Processing single event %s" % event['SUMMARY'].to_ical().decode('utf-8')) logging.info(f"Processing single event {event['SUMMARY'].to_ical().decode('utf-8')}")
dtstart = parse(event['DTSTART'].to_ical()) dtstart = parse(event["DTSTART"].to_ical())
if dtstart >= start and dtstart < end: if dtstart >= start and dtstart < end:
return vevent_to_event(event) return vevent_to_event(event)
else:
return None
def parse_recurring_event(event, start, end): def parse_recurring_event(event, start, end):
logging.info("Processing recurring event %s" % event['SUMMARY'].to_ical().decode('utf-8')) logging.info(f"Processing recurring event {event['SUMMARY'].to_ical().decode('utf-8')}")
dtstart = parse(event['DTSTART'].to_ical()) dtstart = parse(event["DTSTART"].to_ical())
rs = rruleset() rs = rruleset()
rs.rrule(rrulestr(event['RRULE'].to_ical().decode('utf-8'), dtstart=dtstart)) rs.rrule(rrulestr(event["RRULE"].to_ical().decode("utf-8"), dtstart=dtstart))
if 'EXDATE' in event.keys(): if "EXDATE" in event.keys():
exdates = event['EXDATE'] for exdate in event["EXDATE"]:
for exdate in exdates:
rs.exdate(parse(exdate.to_ical())) rs.exdate(parse(exdate.to_ical()))
dates = list(rs)
events = [] events = []
for date in dates: for date in list(rs):
if date >= start and date < end: if date >= start and date < end:
events.append(vevent_to_event(event, date)) events.append(vevent_to_event(event, date))
return events return events
def find_events(icsfilestr, start, end, num): def find_events(icsfilestr, start, end, num):
with open(icsfilestr, 'r') as icsfile: with open(icsfilestr, "r") as icsfile:
cal = icalendar.Calendar.from_ical(icsfile.read()) cal = icalendar.Calendar.from_ical(icsfile.read())
events = [] events = []
for event in cal.subcomponents: for event in cal.subcomponents:
if event.name == 'VEVENT': if event.name == "VEVENT":
if 'RRULE' in event.keys(): if "RRULE" in event.keys():
events = events + parse_recurring_event(event, start, end) events.append(parse_recurring_event(event, start, end))
else: elif ev := parse_single_event(event, start, end) != None:
ev = parse_single_event(event, start, end)
if ev != None:
events.append(ev) events.append(ev)
events = sorted(events, key=lambda k: k['begin']) events = sorted(events, key=lambda k: k["begin"])
events = events[0:num] events = events[0:num]
return events return events
def format_events(events): def format_events(events):
print('<table class="table table-condensed">') print("<table class=\"table table-condensed\">")
for event in events: for event in events:
dateStr = event['begin'].strftime("%A, %d.%m um %H:%M Uhr") print(
#print("<li><a href=\"%s\">%s: %s</a></li>" % (event['url'].decode('utf-8'), dateStr, event['name'].decode('utf-8'))) "<tr>"
print("<tr><td>%s</td><td><a href=\"%s\">%s</a></td></tr>" f"<td>{event['begin'].strftime('%A, %d.%m um %H:%M Uhr')}</td>"
% (dateStr, event['url'].decode('utf-8'), event['name'].decode('utf-8'))) f"<td><a href=\"{event['url'].decode('utf-8')}\">{event['name'].decode('utf-8')}</a></td>"
print('</table>') "</tr>"
)
print("</table><!--/.table /.table-condensed-->")
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) < 3: if len(sys.argv) < 3:
print("Usage: %s calendar max_days max_items" % sys.argv[0]) print(f"Usage: {sys.argv[0]} calendar max_days max_items")
sys.exit(-1) sys.exit(-1)
locale.setlocale(locale.LC_TIME, "de_DE.UTF-8") locale.setlocale(locale.LC_TIME, "de_DE.UTF-8")
@ -85,6 +87,7 @@ if __name__ == "__main__":
max_days = int(sys.argv[2]) max_days = int(sys.argv[2])
max_items = int(sys.argv[3]) max_items = int(sys.argv[3])
events=find_events(calendar, datetime.now(), datetime.now() + timedelta(days=max_days), max_items) now = datetime.now()
events = find_events(calendar, now, now + timedelta(days=max_days), max_items)
format_events(events) format_events(events)

View file

@ -6,22 +6,22 @@ import pytz
import icalendar import icalendar
cals = [] calendars = []
merged = icalendar.Calendar() merged = icalendar.Calendar()
merged.add('prodid', '-//CCCB Calendar Generator//berlin.ccc.de//') merged.add("prodid", "-//CCCB Calendar Generator//berlin.ccc.de//")
merged.add('version', '2.0') merged.add("version", "2.0")
for icsfilestr in glob('public/*/**/*.ics', recursive=True): for icsfilestr in glob("public/*/**/*.ics", recursive=True):
with open(icsfilestr, 'r') as icsfile: with open(icsfilestr, "r") as icsfile:
print('Importing', icsfilestr) print(f"Importing {icsfilestr}")
cals.append(icalendar.Calendar.from_ical(icsfile.read())) calendars.append(icalendar.Calendar.from_ical(icsfile.read()))
for cal in cals: for calendar in calendars:
for e in cal.subcomponents: for event in calendar.subcomponents:
merged.add_component(e) merged.add_component(event)
outfile = 'static/all.ics' outfile = "static/all.ics"
with open(outfile, 'wb') as f: with open(outfile, "wb") as f:
print(f'writing to {outfile}...') print(f"writing to {outfile}...")
f.write(merged.to_ical()) f.write(merged.to_ical())