IEL
4 years ago
commit
332642cbfe
No known key found for this signature in database
GPG Key ID: 5C35763D5E7BFD67
10 changed files with 473 additions and 0 deletions
-
1.DINAR/build-date.txt
-
15.DINAR/config.yaml
-
4.DINAR/image/README.md
-
12.DINAR/image/src/repos.yaml
-
2.github/FUNDING.yml
-
261.github/workflows/DINAR-pr.yml
-
116.github/workflows/DINAR.yml
-
19.github/workflows/main.yml
-
34.github/workflows/repo2store.yml
-
9README.md
@ -0,0 +1 @@ |
|||||
|
April 24, 2020 |
@ -0,0 +1,15 @@ |
|||||
|
addons: |
||||
|
# modules to install before running tests |
||||
|
include: |
||||
|
- contacts |
||||
|
# "contacts" already has mail in dependencies, |
||||
|
# but without the following line DINAR may run odoo odoo with --init=mail,.... |
||||
|
# which leads to error on loading mail's demo data |
||||
|
- mail |
||||
|
|
||||
|
# modules to exclude from installation/testing |
||||
|
exclude: |
||||
|
- hw_proxy |
||||
|
|
||||
|
server_wide_modules: |
||||
|
- web |
@ -0,0 +1,4 @@ |
|||||
|
This folder is attached on image building as `custom/` folder in |
||||
|
[doobba](https://github.com/Tecnativa/doodba#image-usage). Few additional |
||||
|
[files](https://github.com/itpp-labs/DINAR/tree/master/embedded-files/.DINAR/image) are |
||||
|
attached temporary on image building. |
@ -0,0 +1,12 @@ |
|||||
|
# Documentation: https://github.com/Tecnativa/doodba#optodoocustomsrcreposyaml |
||||
|
|
||||
|
# Odoo source. |
||||
|
# Update this section to switch to OCA/OCB or apply custom patches |
||||
|
odoo: |
||||
|
defaults: |
||||
|
depth: 1 |
||||
|
remotes: |
||||
|
origin: https://github.com/odoo/odoo.git |
||||
|
target: origin $ODOO_VERSION |
||||
|
merges: |
||||
|
- origin $ODOO_VERSION |
@ -0,0 +1,2 @@ |
|||||
|
ko_fi: itprojectsllc # This is supposed to bring some coffee for us |
||||
|
patreon: itpp # become our patron |
@ -0,0 +1,261 @@ |
|||||
|
# Copyright 2020 IT Projects Labs |
||||
|
# |
||||
|
# 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. |
||||
|
name: "DINAR" |
||||
|
|
||||
|
on: |
||||
|
pull_request: |
||||
|
|
||||
|
jobs: |
||||
|
pre-commit: |
||||
|
name: "pre-commit" |
||||
|
# Let Quick Review/Tests run first |
||||
|
needs: |
||||
|
- review |
||||
|
- tests |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Checkout Repo |
||||
|
uses: actions/checkout@v2 |
||||
|
- uses: actions/setup-python@v1 |
||||
|
with: |
||||
|
python-version: "3.7.x" |
||||
|
- name: Check Python Version |
||||
|
run: |
||||
|
echo "::set-env name=PY::$(python --version --version | sha256sum | cut -d' ' |
||||
|
-f1)" |
||||
|
- uses: actions/cache@v1 |
||||
|
with: |
||||
|
path: ~/.cache/pre-commit |
||||
|
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} |
||||
|
- uses: pre-commit/action@v1.0.1 |
||||
|
|
||||
|
review: |
||||
|
name: "Quick Review" |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Checkout Repo |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: REPO |
||||
|
- name: Checkout DINAR |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: DINAR |
||||
|
repository: itpp-labs/DINAR-fork |
||||
|
ref: master |
||||
|
- uses: actions/setup-python@v1 |
||||
|
with: |
||||
|
python-version: "3.7.x" |
||||
|
- name: Install python tools |
||||
|
run: | |
||||
|
pip install plumbum PyGithub pyyaml |
||||
|
- name: Analyze PR |
||||
|
run: | |
||||
|
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
||||
|
cd REPO |
||||
|
python ../DINAR/workflow-files/analyze-modules.py updated ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.number }} |
||||
|
- name: Configure docker |
||||
|
run: | |
||||
|
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
||||
|
echo "::set-env name=PR_FILES::../../REPO" |
||||
|
- name: HOW TO RUN ODOO LOCALLY |
||||
|
if: always() |
||||
|
run: | |
||||
|
export MODULES=${{ env.PR_MODULES }} |
||||
|
export LOAD_MODULES=${{ env.PR_MODULES_LOAD }} |
||||
|
export PR_NUM=${{ github.event.number }} |
||||
|
export VERSION=${{ github.event.pull_request.base.ref }} |
||||
|
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
||||
|
export DINAR_REPO="itpp-labs/DINAR-fork" |
||||
|
bash DINAR/workflow-files/how-to-run-locally.sh |
||||
|
- name: Check Python Version |
||||
|
run: |
||||
|
echo "::set-env name=PY::$(python --version --version | sha256sum | cut -d' ' |
||||
|
-f1)" |
||||
|
- uses: actions/cache@v1 |
||||
|
with: |
||||
|
path: ~/.cache/pre-commit |
||||
|
key: pre-commit|${{ env.PY }}|${{ hashFiles('REPO/.pre-commit-config.yaml') }} |
||||
|
- name: Install pre-commit |
||||
|
run: | |
||||
|
pip install pre-commit |
||||
|
- name: PRE-COMMIT against updated files only |
||||
|
run: | |
||||
|
cd REPO |
||||
|
git fetch origin ${{ github.event.pull_request.base.ref }} |
||||
|
pre-commit run --show-diff-on-failure --color=always --show-diff-on-failure --files $(git diff --name-only --no-ext-diff -z ${{ github.event.pull_request.base.ref }}..HEAD) |
||||
|
|
||||
|
tests: |
||||
|
name: "Quick Tests" |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Checkout Repo |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: REPO |
||||
|
- name: Checkout DINAR |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: DINAR |
||||
|
repository: itpp-labs/DINAR-fork |
||||
|
ref: master |
||||
|
- name: Configure docker |
||||
|
run: | |
||||
|
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
||||
|
echo "::set-env name=PR_FILES::../../REPO" |
||||
|
- name: Install python tools |
||||
|
run: | |
||||
|
pip install plumbum PyGithub pyyaml |
||||
|
- name: Download Docker images with preinstalled modules |
||||
|
run: | |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml pull |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --no-start |
||||
|
- name: Analyze PR |
||||
|
run: | |
||||
|
# Get list of installed modules |
||||
|
ODOO_BASE_MODULES=$(docker inspect \ |
||||
|
--format '{{ index .Config.Labels "dinar.odoo.modules"}}' \ |
||||
|
dinar_odoo_1) |
||||
|
echo "ODOO_BASE_MODULES=$ODOO_BASE_MODULES" |
||||
|
|
||||
|
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
||||
|
cd REPO |
||||
|
python ../DINAR/workflow-files/analyze-modules.py updated ${{ secrets.GITHUB_TOKEN }} ${{ github.repository }} ${{ github.event.number }} $ODOO_BASE_MODULES |
||||
|
- name: Install json parser |
||||
|
run: | |
||||
|
sudo apt-get install jq |
||||
|
- name: Install Additional Dependencies (Modules) |
||||
|
if: env.PR_MODULES_DEPS != '' |
||||
|
run: | |
||||
|
# Install new dependencies without tests |
||||
|
export MODULES="${{ env.PR_MODULES_DEPS }}" |
||||
|
export LOAD_MODULES="${{ env.PR_MODULES_LOAD }}" |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
||||
|
- name: Install Additional Dependencies (Packages) |
||||
|
if: env.PR_DEPS != '' |
||||
|
run: | |
||||
|
# TODO https://github.com/itpp-labs/DINAR/issues/42 |
||||
|
exit 1 |
||||
|
- name: Prepare Artifact Folder |
||||
|
run: | |
||||
|
mkdir new-deps/ |
||||
|
# create dummy file to be sure that Artifact will be uploaded |
||||
|
echo ok > new-deps/.empty |
||||
|
echo "::set-env name=ARTIFACT::empty" |
||||
|
- name: Prepare DINAR with additional dependencies |
||||
|
if: env.PR_MODULES_DEPS != '' || env.PR_DEPS != '' |
||||
|
run: | |
||||
|
# Save artifacts for local run and for integrations Tests |
||||
|
bash DINAR/workflow-files/save-docker-layers.sh new-deps/ |
||||
|
echo "${{ env.PR_MODULES_DEPS }}" > new-deps/modules.txt |
||||
|
echo "::set-env name=ARTIFACT::yes" |
||||
|
- name: Save DINAR with dependencies |
||||
|
uses: actions/upload-artifact@v1 |
||||
|
with: |
||||
|
name: new-deps |
||||
|
path: new-deps/ |
||||
|
- name: HOW TO RUN QUICK TESTS LOCALLY |
||||
|
if: always() |
||||
|
run: | |
||||
|
export MODULES=${{ env.PR_MODULES }} |
||||
|
export LOAD_MODULES=${{ env.PR_MODULES_LOAD }} |
||||
|
export PR_NUM=${{ github.event.number }} |
||||
|
export VERSION=${{ github.event.pull_request.base.ref }} |
||||
|
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
||||
|
export DINAR_REPO="itpp-labs/DINAR-fork" |
||||
|
export ODOO_EXTRA_ARG=--test-enable |
||||
|
bash DINAR/workflow-files/how-to-run-locally.sh ${{ secrets.GITHUB_TOKEN }} |
||||
|
- name: Test updated modules |
||||
|
if: env.PR_MODULES != '' |
||||
|
run: | |
||||
|
export MODULES="${{ env.PR_MODULES }}" |
||||
|
export LOAD_MODULES="${{ env.PR_MODULES_LOAD }}" |
||||
|
export ODOO_EXTRA_ARG=--test-enable |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
||||
|
|
||||
|
tests-all: |
||||
|
name: Integration Tests |
||||
|
# Let Quick Review/Tests run first |
||||
|
# This job uses artifacts from "Quick Tests" |
||||
|
needs: |
||||
|
- tests |
||||
|
- review |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Checkout Repo |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: REPO |
||||
|
- name: Checkout DINAR |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: DINAR |
||||
|
repository: itpp-labs/DINAR-fork |
||||
|
ref: master |
||||
|
- name: Install python tools |
||||
|
run: | |
||||
|
pip install plumbum pyyaml |
||||
|
- name: Download Additional Dependencies artifact |
||||
|
uses: actions/download-artifact@v1 |
||||
|
with: |
||||
|
name: new-deps |
||||
|
path: new-deps/ |
||||
|
- name: Check artifact |
||||
|
run: | |
||||
|
if [ ! -f new-deps/modules.txt ]; then |
||||
|
echo "::set-env name=ARTIFACT::empty" |
||||
|
fi |
||||
|
- name: Configure Docker |
||||
|
run: | |
||||
|
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN || secrets.GITHUB_TOKEN }} |
||||
|
echo "::set-env name=PR_FILES::../../REPO" |
||||
|
- name: Analyze PR |
||||
|
run: | |
||||
|
# sets environment variables that available in next steps via $ {{ env.PR_... }} notation |
||||
|
DEPS_MODULES=$(cat new-deps/modules.txt || true) |
||||
|
cd REPO |
||||
|
python ../DINAR/workflow-files/analyze-modules.py all "$DEPS_MODULES" |
||||
|
- name: Install json parser |
||||
|
run: | |
||||
|
sudo apt-get install jq |
||||
|
- name: HOW TO RUN TESTS LOCALLY |
||||
|
if: always() |
||||
|
run: | |
||||
|
export MODULES=${{ env.ALL_MODULES }} |
||||
|
export LOAD_MODULES=${{ env.ALL_MODULES_LOAD }} |
||||
|
export PR_NUM=${{ github.event.number }} |
||||
|
export VERSION=${{ github.event.pull_request.base.ref }} |
||||
|
export REVISION_PR=${{ github.event.pull_request.head.sha}} |
||||
|
export DINAR_REPO="itpp-labs/DINAR-fork" |
||||
|
export ODOO_EXTRA_ARG=--test-enable |
||||
|
bash DINAR/workflow-files/how-to-run-locally.sh ${{ secrets.GITHUB_TOKEN }} |
||||
|
- name: Download base images |
||||
|
run: | |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml pull |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --no-start |
||||
|
- name: Apply new-deps artifact |
||||
|
if: env.ARTIFACT != 'empty' |
||||
|
run: | |
||||
|
bash DINAR/workflow-files/load-docker-layers.sh new-deps/ |
||||
|
- name: Test all modules |
||||
|
run: | |
||||
|
export MODULES="${{ env.ALL_MODULES }}" |
||||
|
export LOAD_MODULES="${{ env.ALL_MODULES_LOAD }}" |
||||
|
export ODOO_EXTRA_ARG=--test-enable |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml config |
||||
|
docker-compose -p DINAR -f DINAR/workflow-files/docker-compose-DINAR-pr.yml up --abort-on-container-exit |
@ -0,0 +1,116 @@ |
|||||
|
# Copyright 2020 IT Projects Labs |
||||
|
# |
||||
|
# 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. |
||||
|
name: "DINAR: Docker Image Building" |
||||
|
|
||||
|
on: |
||||
|
push: |
||||
|
paths: |
||||
|
- ".DINAR/**" |
||||
|
- ".github/workflows/DINAR.yml" |
||||
|
|
||||
|
# Cron works only for defaul branch. See https://github.com/itpp-labs/DINAR/issues/48 |
||||
|
schedule: |
||||
|
- cron: "5 5 * * 0" |
||||
|
|
||||
|
jobs: |
||||
|
check-secret: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Check that DINAR_TOKEN is set |
||||
|
run: | |
||||
|
if [ -z "${{ secrets.DINAR_TOKEN }}" ] |
||||
|
then |
||||
|
echo "DINAR_TOKEN is not set" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
check-branch: |
||||
|
runs-on: ubuntu-latest |
||||
|
steps: |
||||
|
- name: Check that this branch needs docker images |
||||
|
run: | |
||||
|
REF=${GITHUB_BASE_REF:-${GITHUB_REF}} |
||||
|
BRANCH=${REF##*/} |
||||
|
CHECK=$( echo "$BRANCH" | grep -E "^(master|[0-9]+\.[0-9]+)(-dev-.+)?$" || true) |
||||
|
if [ -z "$CHECK" ] |
||||
|
then |
||||
|
echo "This branch is not supposed to be a target of pull requests, so docker image is not needed." |
||||
|
echo "For information check https://github.com/itpp-labs/DINAR/issues/60" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
rebuild-images: |
||||
|
runs-on: ubuntu-latest |
||||
|
needs: |
||||
|
- check-secret |
||||
|
- check-branch |
||||
|
steps: |
||||
|
- name: Checkout Repo |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: REPO |
||||
|
- name: Checkout DINAR |
||||
|
uses: actions/checkout@v2 |
||||
|
with: |
||||
|
path: DINAR |
||||
|
repository: itpp-labs/DINAR-fork |
||||
|
ref: master |
||||
|
- uses: actions/setup-python@v1 |
||||
|
with: |
||||
|
python-version: "3.7.x" |
||||
|
- name: Prepare build folder |
||||
|
run: | |
||||
|
cp -rnT DINAR/embedded-files/ REPO/ |
||||
|
|
||||
|
- name: Configure Docker |
||||
|
run: | |
||||
|
bash DINAR/workflow-files/configure-docker.sh ${{ secrets.DINAR_TOKEN }} |
||||
|
|
||||
|
cat <<- EOF > REPO/.DINAR/image/.netrc |
||||
|
machine github.com |
||||
|
login $GITHUB_ACTOR |
||||
|
password ${{ secrets.DINAR_TOKEN }} |
||||
|
EOF |
||||
|
- name: Build ${{ env.IMAGE_ODOO_BASE }} |
||||
|
uses: elgohr/Publish-Docker-Github-Action@master |
||||
|
env: |
||||
|
LOCAL_CUSTOM_DIR: ./image |
||||
|
AGGREGATE: true |
||||
|
PIP_INSTALL_ODOO: false |
||||
|
CLEAN: false |
||||
|
COMPILE: false |
||||
|
with: |
||||
|
name: ${{ env.IMAGE_ODOO_BASE }} |
||||
|
registry: ${{ env.REGISTRY }} |
||||
|
username: ${{ env.REGISTRY_USERNAME }} |
||||
|
password: ${{ env.REGISTRY_PASSWORD }} |
||||
|
buildargs: ODOO_VERSION,AGGREGATE,PIP_INSTALL_ODOO,CLEAN,COMPILE,LOCAL_CUSTOM_DIR |
||||
|
workdir: REPO/.DINAR/ |
||||
|
- name: Install python tools |
||||
|
run: | |
||||
|
pip install plumbum pyyaml |
||||
|
- name: Compute Modules Dependencies |
||||
|
run: | |
||||
|
# sets environment variables that available in next steps via $ {{ env.VAR_NAME }} notation |
||||
|
cd REPO |
||||
|
python ../DINAR/workflow-files/analyze-modules.py all |
||||
|
- name: Install Base Addons |
||||
|
run: | |
||||
|
export MODULES=$ALL_MODULES_DEPENDENCIES |
||||
|
|
||||
|
export DOODBA_WITHOUT_DEMO=all |
||||
|
bash DINAR/workflow-files/images-with-preinstalled-modules.sh $IMAGE_DB-nodemo $IMAGE_ODOO-nodemo |
||||
|
|
||||
|
export DOODBA_WITHOUT_DEMO=false |
||||
|
bash DINAR/workflow-files/images-with-preinstalled-modules.sh $IMAGE_DB $IMAGE_ODOO |
@ -0,0 +1,19 @@ |
|||||
|
name: Telegram Notifications |
||||
|
|
||||
|
on: |
||||
|
issues: |
||||
|
types: [opened, reopened, deleted, closed] |
||||
|
|
||||
|
jobs: |
||||
|
notify: |
||||
|
runs-on: ubuntu-latest |
||||
|
|
||||
|
steps: |
||||
|
- name: Send notifications to Telegram |
||||
|
run: |
||||
|
curl -s -X POST https://api.telegram.org/bot${{ secrets.TELEGRAM_TOKEN |
||||
|
}}/sendMessage -d chat_id=${{ secrets.TELEGRAM_CHAT_ID }} -d text="${MESSAGE}" |
||||
|
>> /dev/null |
||||
|
env: |
||||
|
MESSAGE: |
||||
|
"Issue ${{ github.event.action }}: \n${{ github.event.issue.html_url }}" |
@ -0,0 +1,34 @@ |
|||||
|
name: "Push Updates to REPO-store" |
||||
|
|
||||
|
on: |
||||
|
push: |
||||
|
|
||||
|
jobs: |
||||
|
repo2store: |
||||
|
runs-on: ubuntu-latest |
||||
|
if: |
||||
|
"! endsWith(github.repository, '-store') && startsWith(github.repository, |
||||
|
'itpp-labs/')" |
||||
|
steps: |
||||
|
- name: Checkout REPO |
||||
|
uses: actions/checkout@v2-beta |
||||
|
with: |
||||
|
fetch-depth: 0 |
||||
|
# custom token is not needed for fetching REPO, |
||||
|
# but the action makes some magic with authentication headers |
||||
|
# which are used on pushing to REPO-store |
||||
|
token: ${{ secrets.DINAR_TOKEN }} |
||||
|
- name: Fetch REPO-store |
||||
|
run: | |
||||
|
git remote add store https://x-access-token:${{ secrets.DINAR_TOKEN }}@github.com/${GITHUB_REPOSITORY}-store.git |
||||
|
git fetch store |
||||
|
- name: Merge and Push |
||||
|
run: | |
||||
|
set -x |
||||
|
git config --global user.email "itpp-bot@users.noreply.github.com" |
||||
|
git config --global user.name "Mitchell Admin" |
||||
|
BRANCH=${GITHUB_REF##*/} |
||||
|
REF=$(git rev-parse HEAD) |
||||
|
git checkout -b $BRANCH-store store/$BRANCH |
||||
|
git merge origin/$BRANCH $REF |
||||
|
git push store $BRANCH-store:$BRANCH |
@ -0,0 +1,9 @@ |
|||||
|
List of repositories |
||||
|
==================== |
||||
|
|
||||
|
* https://github.com/itpp-labs/pos-addons |
||||
|
* https://github.com/itpp-labs/mail-addons |
||||
|
* https://github.com/itpp-labs/misc-addons |
||||
|
* https://github.com/itpp-labs/sync-addons |
||||
|
* https://github.com/itpp-labs/access-addons |
||||
|
* https://github.com/itpp-labs/website-addons |
Write
Preview
Loading…
Cancel
Save
Reference in new issue