diff --git a/Dockerfile.sync-page b/Dockerfile.sync-page new file mode 100644 index 00000000..e707114d --- /dev/null +++ b/Dockerfile.sync-page @@ -0,0 +1,49 @@ +FROM fedora:latest +LABEL \ + name="sync2jira" \ + description="sync2jira application" \ + vendor="sync2jira developers" \ + license="GPLv2+" \ + build-date="" + +# Installing sync2jira dependencies +RUN dnf -y install \ + git \ + python3-pip \ + python3-requests \ + python3-jira \ + python3-fedmsg-core \ + python3-pygithub \ + python3-jinja2 \ + python3-pypandoc \ + python3-requests-kerberos \ + python3-flask \ + && dnf -y clean all + +ARG SYNC2JIRA_GIT_REPO=https://github.com/release-engineering/Sync2Jira.git +ARG SYNC2JIRA_GIT_REF=master +ARG SYNC2JIRA_CACERT_URL= +ARG SYNC2JIRA_VERSION= +ENV SYNC2JIRA_VERSION=$SYNC2JIRA_VERSION +ENV SYNC2JIRA_CACERT_URL=$SYNC2JIRA_CACERT_URL + +USER root + +# Create Sync2Jira folder +RUN mkdir -p /usr/local/src/sync2jira + +# Copy over our repo +COPY . /usr/local/src/sync2jira + +# Install Sync2Jira +RUN pip3 install --no-deps -v /usr/local/src/sync2jira + +# To deal with JIRA issues (i.e. SSL errors) +RUN chmod g+w /etc/pki/tls/certs/ca-bundle.crt +RUN chmod 777 /usr/local/src/sync2jira/openshift/docker-entrypoint.sh + +USER 1001 + +ENTRYPOINT ["/usr/local/src/sync2jira/openshift/docker-entrypoint.sh"] + +CMD ["python3", "/usr/local/src/sync2jira/sync-page/event-handler.py"] diff --git a/openshift/sync2jira-sync-page-template.yaml b/openshift/sync2jira-sync-page-template.yaml new file mode 100644 index 00000000..9517eb36 --- /dev/null +++ b/openshift/sync2jira-sync-page-template.yaml @@ -0,0 +1,176 @@ +apiVersion: v1 +kind: Template +metadata: + name: sync2jira-sync-page-template + app: sync2jira-sync-page +labels: + app: sync2jira-sync-page +parameters: +- name: CA_URL + displayName: CA URL used for sync2jira + required: true +- name: DEFAULT_SERVER + displayName: Default server to use for mailing + required: true +- name: DEFAULT_FROM + displayName: Default from to use for mailing + required: true +- name: USER + displayName: JIRA username + required: true +- name: CONFLUENCE_SPACE + displayName: Confluence space + required: true + value: "mock_confluence_space" +- name: INITILIZE + displayName: True/False Initilize our repos on startup + value: "0" +- name: IMAGE_URL + displayName: Image URL:TAG to pull from + value: "quay.io/redhat-aqe/sync2jira:sync-page" +- name: JIRA_PNT_PASS + displayName: PNT password in base64 + requiered: true +- name: JIRA_OMEGAPRIME_PASS + displayName: Omegaprime password in base64 + requiered: true +- name: GITHUB_TOKEN + displayName: GitHub token in base64 + requiered: true +- name: PAAS_DOMAIN + displayName: Domain to use for the service + requiered: true +objects: +- apiVersion: v1 + kind: ImageStream + metadata: + labels: + app: sync2jira-sync-page + annotations: + openshift.io/display-name: sync2jira-sync-page + name: sync2jira-sync-page + spec: + lookupPolicy: + local: false + tags: + - from: + kind: DockerImage + name: ${IMAGE_URL} + name: latest + referencePolicy: + type: Source +- apiVersion: v1 + kind: Secret + metadata: + name: sync2jira-secret + labels: + app: sync2jira-stage + data: + jira_pnt_pass: |- + ${JIRA_PNT_PASS} + jira_omegaprime_pass: |- + ${JIRA_OMEGAPRIME_PASS} + sync2jira-confluence: |- + ${SYNC2JIRA_CONFLUENCE_PASS} + github_token: |- + ${GITHUB_TOKEN} +- apiVersion: v1 + kind: Route + metadata: + name: sync2jira-sync-page + labels: + app: sync2jira-sync-page + spec: + host: sync2jira-page-sync.${PAAS_DOMAIN} + to: + kind: Service + name: sync2jira-sync-page + port: + targetPort: http +- apiVersion: v1 + kind: Service + metadata: + name: sync2jira-sync-page + labels: + app: sync2jira-sync-page + spec: + selector: + service: sync2jira-sync-page + ports: + - name: http + port: 80 + targetPort: http +- apiVersion: v1 + kind: DeploymentConfig + metadata: + name: sync2jira-sync-page + labels: + app: sync2jira-sync-page + spec: + selector: + service: sync2jira-sync-page + template: + metadata: + labels: + app: sync2jira-sync-page + service: sync2jira-sync-page + spec: + containers: + - name: sync2jira-sync-page-container + image: sync2jira-sync-page:latest + imagePullPolicy: Always + ports: + - name: http + containerPort: 5000 + volumeMounts: + - name: fedmsgd-volume + mountPath: /etc/fedmsg.d + readOnly: true + env: + - name: BASE_URL + value: 0.0.0.0 + - name: REDIRECT_URL + value: sync2jira-page-sync.${PAAS_DOMAIN} + - name: INITIALIZE + value: ${INITILIZE} + - name: CA_URL + value: ${CA_URL} + - name: DEFAULT_SERVER + value: ${DEFAULT_SERVER} + - name: DEFAULT_FROM + value: ${DEFAULT_FROM} + - name: USER + value: ${USER} + - name: SYNC2JIRA_PNTJIRA_PASS + valueFrom: + secretKeyRef: + key: jira_pnt_pass + name: sync2jira-secret + - name: SYNC2JIRA_OMEGAPRIME_PASS + valueFrom: + secretKeyRef: + key: jira_omegaprime_pass + name: sync2jira-secret + - name: SYNC2JIRA_GITHUB_TOKEN + valueFrom: + secretKeyRef: + key: github_token + name: sync2jira-secret + - name: CONFLUENCE_SPACE + value: ${CONFLUENCE_SPACE} + - name: INITILIZE + value: ${INITILIZE} + volumes: + - name: fedmsgd-volume + configMap: + name: fedmsgd + triggers: + - type: ImageChange + imageChangeParams: + automatic: true + containerNames: + - sync2jira-sync-page-container + from: + kind: ImageStreamTag + name: sync2jira-sync-page:latest + - type: ConfigChange diff --git a/sync-page/__init__.py b/sync-page/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sync-page/assets/font.css b/sync-page/assets/font.css new file mode 100644 index 00000000..c795562b --- /dev/null +++ b/sync-page/assets/font.css @@ -0,0 +1,162 @@ + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 200; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin.eot"); + /* IE9 Compat Modes */ + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin.ttf") format("truetype"); + /* Safari, Android, iOS */ + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 200; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-thin-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 300; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 300; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extralight-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 400; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 400; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-light-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 500; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-regular.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-regular.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-regular.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-regular.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-regular.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 500; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 600; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 600; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-semibold-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 700; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 700; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-bold-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 800; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 800; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-extrabold-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: normal; + font-weight: 900; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass"; + font-style: italic; + font-weight: 900; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy-italic.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy-italic.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy-italic.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy-italic.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-webfont/overpass-heavy-italic.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass-mono"; + font-style: normal; + font-weight: 300; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-light.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-light.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-light.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-light.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-light.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass-mono"; + font-style: normal; + font-weight: 400; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-regular.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-regular.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-regular.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-regular.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-regular.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass-mono"; + font-style: normal; + font-weight: 500; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-semibold.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-semibold.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-semibold.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-semibold.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-semibold.ttf") format("truetype"); + } + + @font-face { + font-family: "overpass-mono"; + font-style: normal; + font-weight: 600; + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-bold.eot"); + src: url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-bold.eot?#iefix") format("embedded-opentype"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-bold.woff2") format("woff2"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-bold.woff") format("woff"), url("https://unpkg.com/@patternfly/patternfly@2.40.13/assets/fonts/overpass-mono-webfont/overpass-mono-bold.ttf") format("truetype"); + } diff --git a/sync-page/assets/redhat-favicon.ico b/sync-page/assets/redhat-favicon.ico new file mode 100644 index 00000000..9072de7b Binary files /dev/null and b/sync-page/assets/redhat-favicon.ico differ diff --git a/sync-page/event-handler.py b/sync-page/event-handler.py new file mode 100644 index 00000000..64995836 --- /dev/null +++ b/sync-page/event-handler.py @@ -0,0 +1,74 @@ +# Build-In Modules +import logging +import os + +# 3rd Party Modules +from flask import Flask, render_template, request, redirect + +# Local Modules +from sync2jira.main import load_config, initialize_pr, initialize_issues + +# Global Variables +app = Flask(__name__, static_url_path = "/assets", static_folder = "assets") +BASE_URL = os.environ['BASE_URL'] +REDIRECT_URL = os.environ['REDIRECT_URL'] +config = load_config() + +# Set up our logging +FORMAT = "[%(asctime)s] %(levelname)s: %(message)s" +logging.basicConfig(format=FORMAT, level=logging.INFO) +logging.basicConfig(format=FORMAT, level=logging.DEBUG) +logging.basicConfig(format=FORMAT, level=logging.WARNING) +log = logging.getLogger('sync2jira-sync-page') + + +@app.route('/handle-event', methods=['POST']) +def handle_event(): + """ + Handler for when a user wants to sync a repo + """ + response = request.form + synced_repos = [] + for repo_name, switch in response.items(): + if switch == "on": + # Sync repo_name + log.info(f"Starting sync for repo: {repo_name}") + synced_repos.append(repo_name) + if synced_repos: + return render_template('sync-page-success.jinja', + synced_repos=synced_repos, + url=f"http://{REDIRECT_URL}:5000") + else: + return render_template('sync-page-failure.jinja', + url=f"http://{REDIRECT_URL}:5000") + + +@app.route('/', methods=['GET']) +def index(): + """ + Return relevant redirect + """ + return redirect("/github") + +@app.route('/github', methods=['GET']) +def github(): + """ + Github Sync Page + """ + # Build and return our updated HTML page + return render_template('sync-page-github.jinja', + github=config['sync2jira']['map']['github'], + url=f"http://{REDIRECT_URL}:5000") + +@app.route('/pagure', methods=['GET']) +def pagure(): + """ + Pagure Sync Page + """ + # Build and return our updated HTML page + return render_template('sync-page-pagure.jinja', + pagure=config['sync2jira']['map']['pagure'], + url=f"http://{REDIRECT_URL}:5000") + +if __name__ == '__main__': + app.run(host=BASE_URL) diff --git a/sync-page/templates/sync-page-failure.jinja b/sync-page/templates/sync-page-failure.jinja new file mode 100644 index 00000000..5f64b0d7 --- /dev/null +++ b/sync-page/templates/sync-page-failure.jinja @@ -0,0 +1,70 @@ + + + + + + + + + + + Sync2Jira - Sync Page + + + +
+ +
+
+ +
+
+
+
+
+

Failed to started syncing

+

Make sure you selected at least one repo!

+
+
+
+
+
+
+ +
+
+
+
+
+
+ + diff --git a/sync-page/templates/sync-page-github.jinja b/sync-page/templates/sync-page-github.jinja new file mode 100644 index 00000000..fd9dbbf2 --- /dev/null +++ b/sync-page/templates/sync-page-github.jinja @@ -0,0 +1,77 @@ + + + + + + + + + + + Sync2Jira - Sync Page + + +
+ +
+
+ +
+
+
+
+
+

GitHub Sync

+

Select the repos you would like to be re-syned!

+
+
+
+
+ {% for repo_name, info in github.items() %} +
+
+
+ + +
+
+
+ {% endfor %} +
+
+
+ +
+
+
+
+
+
+
+ + diff --git a/sync-page/templates/sync-page-pagure.jinja b/sync-page/templates/sync-page-pagure.jinja new file mode 100644 index 00000000..45bdb598 --- /dev/null +++ b/sync-page/templates/sync-page-pagure.jinja @@ -0,0 +1,77 @@ + + + + + + + + + + + Sync2Jira - Sync Page + + +
+ +
+
+ +
+
+
+
+
+

Pagure Sync

+

Select the repos you would like to be re-syned!

+
+
+
+
+ {% for repo_name, info in pagure.items() %} +
+
+
+ + +
+
+
+ {% endfor %} +
+
+
+ +
+
+
+
+
+
+
+ + diff --git a/sync-page/templates/sync-page-success.jinja b/sync-page/templates/sync-page-success.jinja new file mode 100644 index 00000000..440ee789 --- /dev/null +++ b/sync-page/templates/sync-page-success.jinja @@ -0,0 +1,74 @@ + + + + + + + + + + + Sync2Jira - Sync Page + + + +
+ +
+
+ +
+
+
+
+
+

Successfully started syncing the following repos:

+
    + {% for repo_name in synced_repos %} +
  • {{ repo_name }}
  • + {% endfor %} +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + diff --git a/sync2jira/main.py b/sync2jira/main.py index 3f475841..198afe29 100644 --- a/sync2jira/main.py +++ b/sync2jira/main.py @@ -53,9 +53,12 @@ log = logging.getLogger('sync2jira') if os.environ.get('CONFLUENCE_SPACE') == 'mock_confluence_space': # If we are debugging save log output - hdlr = logging.FileHandler('sync2jira_main.log') - log.addHandler(hdlr) - log.setLevel(logging.DEBUG) + try: + hdlr = logging.FileHandler('sync2jira_main.log') + log.addHandler(hdlr) + log.setLevel(logging.DEBUG) + except: # noqa: E722 + log.error("Unable to create log file!") # Only allow fedmsg logs that are critical fedmsg_log = logging.getLogger('fedmsg.crypto.utils') @@ -177,7 +180,7 @@ def listen(config): handle_msg(msg, suffix, config) -def initialize_issues(config, testing=False): +def initialize_issues(config, testing=False, repo_name=None): """ Initial initialization needed to sync any upstream \ repo with JIRA. Goes through all issues and \ @@ -186,6 +189,7 @@ def initialize_issues(config, testing=False): :param Dict config: Config dict for JIRA :param Bool testing: Flag to indicate if we are testing. Default false + :param String repo_name: Optional individual repo name. If defined we will only sync the provided repo :returns: Nothing """ log.info("Running initialization to sync all issues from upstream to jira") @@ -194,6 +198,8 @@ def initialize_issues(config, testing=False): for upstream in mapping.get('pagure', {}).keys(): if 'issue' not in mapping.get('pagure', {}).get(upstream, {}).get('sync', []): continue + if repo_name is not None and upstream != repo_name: + continue for issue in u_issue.pagure_issues(upstream, config): try: d_issue.sync_with_jira(issue, config) @@ -205,6 +211,8 @@ def initialize_issues(config, testing=False): for upstream in mapping.get('github', {}).keys(): if 'issue' not in mapping.get('github', {}).get(upstream, {}).get('sync', []): continue + if repo_name is not None and upstream != repo_name: + continue # Try and except for github API limit try: for issue in u_issue.github_issues(upstream, config): @@ -230,7 +238,7 @@ def initialize_issues(config, testing=False): log.info("Done with github issue initialization.") -def initialize_pr(config, testing=False): +def initialize_pr(config, testing=False, repo_name=None): """ Initial initialization needed to sync any upstream \ repo with JIRA. Goes through all PRs and \ @@ -239,6 +247,7 @@ def initialize_pr(config, testing=False): :param Dict config: Config dict for JIRA :param Bool testing: Flag to indicate if we are testing. Default false + :param String repo_name: Optional individual repo name. If defined we will only sync the provided repo :returns: Nothing """ log.info("Running initialization to sync all PRs from upstream to jira") @@ -247,6 +256,8 @@ def initialize_pr(config, testing=False): for upstream in mapping.get('pagure', {}).keys(): if 'pullrequest' not in mapping.get('pagure', {}).get(upstream, {}).get('sync', []): continue + if repo_name is not None and upstream != repo_name: + continue for pr in u_pr.pagure_prs(upstream, config): if pr: d_pr.sync_with_jira(pr, config) @@ -255,6 +266,8 @@ def initialize_pr(config, testing=False): for upstream in mapping.get('github', {}).keys(): if 'pullrequest' not in mapping.get('github', {}).get(upstream, {}).get('sync', []): continue + if repo_name is not None and upstream != repo_name: + continue # Try and except for github API limit try: for pr in u_pr.github_prs(upstream, config): diff --git a/tests/test_main.py b/tests/test_main.py index 0d3f0927..0c76be63 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -234,6 +234,46 @@ def test_initialize(self, mock_d.sync_with_jira.assert_any_call('mock_issue_pagure', self.mock_config) mock_d.sync_with_jira.assert_any_call('mock_issue_github', self.mock_config) + @mock.patch(PATH + 'u_issue') + @mock.patch(PATH + 'd_issue') + def test_initialize_repo_name_pagure(self, + mock_d, + mock_u): + """ + This tests 'initialize' function where we want to sync an individual repo for Pagure + """ + # Set up return values + mock_u.pagure_issues.return_value = ['mock_issue_pagure'] + mock_u.github_issues.return_value = ['mock_issue_github'] + + # Call the function + m.initialize_issues(self.mock_config, repo_name='key_pagure') + + # Assert everything was called correctly + mock_u.pagure_issues.assert_called_with('key_pagure', self.mock_config) + mock_u.github_issues.assert_not_called() + mock_d.sync_with_jira.assert_called_with('mock_issue_pagure', self.mock_config) + + @mock.patch(PATH + 'u_issue') + @mock.patch(PATH + 'd_issue') + def test_initialize_repo_name_github(self, + mock_d, + mock_u): + """ + This tests 'initialize' function where we want to sync an individual repo for GitHub + """ + # Set up return values + mock_u.pagure_issues.return_value = ['mock_issue_pagure'] + mock_u.github_issues.return_value = ['mock_issue_github'] + + # Call the function + m.initialize_issues(self.mock_config, repo_name='key_github') + + # Assert everything was called correctly + mock_u.github_issues.assert_called_with('key_github', self.mock_config) + mock_u.pagure_issues.assert_not_called() + mock_d.sync_with_jira.assert_called_with('mock_issue_github', self.mock_config) + @mock.patch(PATH + 'u_issue') @mock.patch(PATH + 'd_issue') def test_initialize_errors(self,