From 077510d22d696fa21ffb67408bb8a6bc843ebea1 Mon Sep 17 00:00:00 2001 From: Sidhartha Premkumar Date: Mon, 18 May 2020 12:37:07 -0400 Subject: [PATCH] Add microservice to sync individual repos --- Dockerfile.sync-page | 49 ++++++ openshift/sync2jira-sync-page-template.yaml | 176 ++++++++++++++++++++ sync-page/__init__.py | 0 sync-page/assets/font.css | 162 ++++++++++++++++++ sync-page/assets/redhat-favicon.ico | Bin 0 -> 7288 bytes sync-page/event-handler.py | 74 ++++++++ sync-page/templates/sync-page-failure.jinja | 70 ++++++++ sync-page/templates/sync-page-github.jinja | 77 +++++++++ sync-page/templates/sync-page-pagure.jinja | 77 +++++++++ sync-page/templates/sync-page-success.jinja | 74 ++++++++ sync2jira/main.py | 23 ++- tests/test_main.py | 40 +++++ 12 files changed, 817 insertions(+), 5 deletions(-) create mode 100644 Dockerfile.sync-page create mode 100644 openshift/sync2jira-sync-page-template.yaml create mode 100644 sync-page/__init__.py create mode 100644 sync-page/assets/font.css create mode 100644 sync-page/assets/redhat-favicon.ico create mode 100644 sync-page/event-handler.py create mode 100644 sync-page/templates/sync-page-failure.jinja create mode 100644 sync-page/templates/sync-page-github.jinja create mode 100644 sync-page/templates/sync-page-pagure.jinja create mode 100644 sync-page/templates/sync-page-success.jinja diff --git a/Dockerfile.sync-page b/Dockerfile.sync-page new file mode 100644 index 0000000..e707114 --- /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 0000000..9517eb3 --- /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 0000000..e69de29 diff --git a/sync-page/assets/font.css b/sync-page/assets/font.css new file mode 100644 index 0000000..c795562 --- /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 0000000000000000000000000000000000000000..9072de7bf3bbefcdb155fec2183881c1824dfea7 GIT binary patch literal 7288 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 bk-)Zx&n3(ZQo{fK4gm(bCa5}XboBoLE;N4| literal 0 HcmV?d00001 diff --git a/sync-page/event-handler.py b/sync-page/event-handler.py new file mode 100644 index 0000000..6499583 --- /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 0000000..5f64b0d --- /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 0000000..fd9dbbf --- /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 0000000..45bdb59 --- /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 0000000..440ee78 --- /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 3f47584..198afe2 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 0d3f092..0c76be6 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,