c2cgeoportal-geoportal 2.7.1.156__py2.py3-none-any.whl → 2.8.1.87__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. c2cgeoportal_geoportal/__init__.py +23 -14
  2. c2cgeoportal_geoportal/lib/__init__.py +3 -5
  3. c2cgeoportal_geoportal/lib/authentication.py +10 -14
  4. c2cgeoportal_geoportal/lib/caching.py +8 -6
  5. c2cgeoportal_geoportal/lib/checker.py +10 -6
  6. c2cgeoportal_geoportal/lib/common_headers.py +2 -2
  7. c2cgeoportal_geoportal/lib/dbreflection.py +8 -8
  8. c2cgeoportal_geoportal/lib/filter_capabilities.py +8 -6
  9. c2cgeoportal_geoportal/lib/lingua_extractor.py +11 -12
  10. c2cgeoportal_geoportal/lib/loader.py +1 -1
  11. c2cgeoportal_geoportal/lib/oauth2.py +217 -100
  12. c2cgeoportal_geoportal/lib/wmstparsing.py +8 -12
  13. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/Dockerfile +9 -11
  14. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/development.ini +1 -1
  15. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/gunicorn.conf.py +3 -3
  16. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/requirements.txt +1 -1
  17. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.api.js +6 -4
  18. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.apps.js +1 -3
  19. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/webpack.commons.js +1 -0
  20. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__.py +1 -6
  21. c2cgeoportal_geoportal/scaffolds/advance_update/{{cookiecutter.project}}/geoportal/CONST_Makefile +0 -20
  22. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/main.yaml +21 -7
  23. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/rebuild.yaml +1 -1
  24. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/.github/workflows/update_l10n.yaml +2 -1
  25. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Dockerfile +22 -22
  26. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/Makefile +58 -2
  27. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/build +49 -29
  28. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/config.yaml +2 -5
  29. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/docker-compose-check +25 -0
  30. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/ci/requirements.txt +1 -1
  31. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-db.yaml +26 -0
  32. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-lib.yaml +35 -26
  33. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose-qgis.yaml +23 -0
  34. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.override.sample.yaml +0 -2
  35. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/docker-compose.yaml +3 -3
  36. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.default +21 -2
  37. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/env.project +9 -0
  38. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/geoportal/vars.yaml +38 -14
  39. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/data/Readme.txt +2 -2
  40. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.conf +15 -0
  41. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/mapserver/mapserver.map.tmpl +2 -3
  42. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Landscape.jrxml +5 -0
  43. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A3_Portrait.jrxml +5 -0
  44. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Landscape.jrxml +5 -0
  45. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/A4_Portrait.jrxml +5 -0
  46. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/print/print-apps/{{cookiecutter.package}}/config.yaml.tmpl +6 -0
  47. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/pyproject.toml +4 -0
  48. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/run_alembic.sh +3 -5
  49. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-backup +5 -8
  50. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/scripts/db-restore +5 -8
  51. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/spell-ignore-words.txt +2 -0
  52. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/__init__.py +0 -0
  53. c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter.project}}/tests/test_app.py +38 -0
  54. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/.upgrade.yaml +2 -132
  55. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_CHANGELOG.txt +200 -1105
  56. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/CONST_create_template/tests/test_testapp.py +48 -0
  57. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_config-schema.yaml +17 -15
  58. c2cgeoportal_geoportal/scaffolds/update/{{cookiecutter.project}}/geoportal/CONST_vars.yaml +48 -2
  59. c2cgeoportal_geoportal/scripts/__init__.py +3 -5
  60. c2cgeoportal_geoportal/scripts/c2cupgrade.py +1 -2
  61. c2cgeoportal_geoportal/scripts/pcreate.py +8 -10
  62. c2cgeoportal_geoportal/scripts/theme2fts.py +58 -3
  63. c2cgeoportal_geoportal/scripts/urllogin.py +2 -2
  64. c2cgeoportal_geoportal/views/__init__.py +1 -3
  65. c2cgeoportal_geoportal/views/dynamic.py +2 -3
  66. c2cgeoportal_geoportal/views/entry.py +2 -10
  67. c2cgeoportal_geoportal/views/fulltextsearch.py +1 -1
  68. c2cgeoportal_geoportal/views/geometry_processing.py +3 -3
  69. c2cgeoportal_geoportal/views/layers.py +10 -11
  70. c2cgeoportal_geoportal/views/login.py +63 -8
  71. c2cgeoportal_geoportal/views/mapserverproxy.py +3 -4
  72. c2cgeoportal_geoportal/views/ogcproxy.py +6 -2
  73. c2cgeoportal_geoportal/views/pdfreport.py +1 -1
  74. c2cgeoportal_geoportal/views/printproxy.py +6 -8
  75. c2cgeoportal_geoportal/views/profile.py +1 -1
  76. c2cgeoportal_geoportal/views/proxy.py +6 -9
  77. c2cgeoportal_geoportal/views/raster.py +2 -2
  78. c2cgeoportal_geoportal/views/resourceproxy.py +1 -1
  79. c2cgeoportal_geoportal/views/shortener.py +1 -2
  80. c2cgeoportal_geoportal/views/theme.py +97 -61
  81. c2cgeoportal_geoportal/views/tinyowsproxy.py +3 -12
  82. c2cgeoportal_geoportal/views/vector_tiles.py +1 -1
  83. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/METADATA +20 -15
  84. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/RECORD +100 -94
  85. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/entry_points.txt +1 -0
  86. tests/__init__.py +3 -2
  87. tests/test_cachebuster.py +3 -3
  88. tests/test_caching.py +1 -1
  89. tests/test_checker.py +1 -1
  90. tests/test_decimaljson.py +1 -1
  91. tests/test_headerstween.py +1 -1
  92. tests/test_i18n.py +1 -1
  93. tests/test_init.py +14 -15
  94. tests/test_locale_negociator.py +4 -4
  95. tests/test_mapserverproxy_route_predicate.py +1 -2
  96. tests/test_raster.py +15 -15
  97. tests/test_wmstparsing.py +10 -10
  98. tests/xmlstr.py +1 -3
  99. c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/tools/extract-messages.js +0 -41
  100. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/WHEEL +0 -0
  101. {c2cgeoportal_geoportal-2.7.1.156.dist-info → c2cgeoportal_geoportal-2.8.1.87.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2013-2024, Camptocamp SA
1
+ # Copyright (c) 2013-2023, Camptocamp SA
2
2
  # All rights reserved.
3
3
 
4
4
  # Redistribution and use in source and binary forms, with or without
@@ -131,7 +131,7 @@ class TimeExtentValue:
131
131
  max_def_value: Optional[datetime.datetime],
132
132
  ):
133
133
  """
134
- Initialise.
134
+ Initialize.
135
135
 
136
136
  Arguments:
137
137
 
@@ -212,20 +212,16 @@ class TimeExtentInterval:
212
212
  self.min_def_value = (
213
213
  self.min_def_value
214
214
  if extent.min_def_value is None
215
- else (
216
- extent.min_def_value
217
- if self.min_def_value is None
218
- else min_none(self.min_def_value, extent.min_def_value)
219
- )
215
+ else extent.min_def_value
216
+ if self.min_def_value is None
217
+ else min_none(self.min_def_value, extent.min_def_value)
220
218
  )
221
219
  self.max_def_value = (
222
220
  self.max_def_value
223
221
  if extent.max_def_value is None
224
- else (
225
- extent.max_def_value
226
- if self.max_def_value is None
227
- else max_none(self.max_def_value, extent.max_def_value)
228
- )
222
+ else extent.max_def_value
223
+ if self.max_def_value is None
224
+ else max_none(self.max_def_value, extent.max_def_value)
229
225
  )
230
226
 
231
227
  def to_dict(self) -> Dict[str, Any]:
@@ -5,9 +5,8 @@ FROM camptocamp/geomapfish-tools:{{cookiecutter.geomapfish_version_tag_env}} as
5
5
  LABEL maintainer Camptocamp "info@camptocamp.com"
6
6
 
7
7
  COPY requirements.txt /tmp/requirements.txt
8
- RUN \
9
- python3 -m pip install --disable-pip-version-check --no-cache-dir --requirement=/tmp/requirements.txt && \
10
- rm --recursive --force /tmp/* /var/tmp/* /root/.cache/*
8
+ RUN --mount=type=cache,target=/root/.cache \
9
+ python3 -m pip install --disable-pip-version-check --requirement=/tmp/requirements.txt
11
10
 
12
11
  WORKDIR /app
13
12
  COPY webpack.*.js Makefile CONST_Makefile /app/
@@ -16,7 +15,6 @@ RUN make apps
16
15
 
17
16
  COPY . /app
18
17
 
19
- RUN make checks
20
18
  RUN make build
21
19
  RUN mv webpack.apps.js webpack.apps.js.tmpl
22
20
 
@@ -28,9 +26,8 @@ CMD [ "webpack-dev-server", "--mode=development", "--debug", "--watch", "--no-in
28
26
  FROM camptocamp/geomapfish:{{cookiecutter.geomapfish_major_version_tag_env}} as runner
29
27
 
30
28
  COPY requirements.txt /tmp/requirements.txt
31
- RUN \
32
- python3 -m pip install --disable-pip-version-check --no-cache-dir --requirement=/tmp/requirements.txt && \
33
- rm --recursive --force /tmp/* /var/tmp/* /root/.cache/*
29
+ RUN --mount=type=cache,target=/root/.cache \
30
+ python3 -m pip install --disable-pip-version-check --requirement=/tmp/requirements.txt
34
31
 
35
32
  WORKDIR /app
36
33
  COPY . /app
@@ -41,10 +38,11 @@ COPY --from=builder /etc/static-ngeo/* /etc/static-ngeo/
41
38
  COPY --from=builder /app/alembic.ini /app/alembic.yaml ./
42
39
  RUN chmod go+w /etc/static-ngeo/
43
40
 
44
- RUN python3 -m pip install --disable-pip-version-check --no-cache-dir --editable=/app/ && \
45
- python3 -m compileall -q /usr/local/lib/python3.* \
46
- -x '/(debugpy|pipenv|.*pydev.*|networkx)/' && \
47
- python3 -m compileall -q /app/{{cookiecutter.package}}_geoportal -x /app/{{cookiecutter.package}}_geoportal/static.*
41
+ RUN --mount=type=cache,target=/root/.cache \
42
+ python3 -m pip install --disable-pip-version-check --editable=/app/ \
43
+ && python3 -m compileall -q /usr/local/lib/python3.* \
44
+ -x '/(ptvsd|.*pydev.*|networkx)/' \
45
+ && python3 -m compileall -q /app/{{cookiecutter.package}}_geoportal -x /app/{{cookiecutter.package}}_geoportal/static.*
48
46
 
49
47
  ARG GIT_HASH
50
48
  RUN c2cwsgiutils-genversion ${GIT_HASH}
@@ -48,7 +48,7 @@ use = egg:PasteDeploy#prefix
48
48
  prefix = %(VISIBLE_ENTRY_POINT)s
49
49
 
50
50
  [pipeline:main]
51
- pipeline = egg:c2cwsgiutils#client_info egg:c2cwsgiutils#profiler egg:c2cwsgiutils#sentry app
51
+ pipeline = egg:c2cwsgiutils#client_info egg:c2cwsgiutils#sentry app
52
52
 
53
53
  ###
54
54
  # logging configuration
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2019-2024, Camptocamp SA
1
+ # Copyright (c) 2019-2023, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -49,6 +47,8 @@ max_requests_jitter = int(os.environ.get("GUNICORN_MAX_REQUESTS_JITTER", 100))
49
47
  worker_tmp_dir = "/dev/shm" # nosec
50
48
  limit_request_line = int(os.environ.get("GUNICORN_LIMIT_REQUEST_LINE", 8190))
51
49
 
50
+ preload = "true"
51
+
52
52
  accesslog = "-"
53
53
  access_log_format = os.environ.get(
54
54
  "GUNICORN_ACCESS_LOG_FORMAT",
@@ -1,2 +1,2 @@
1
- #debugpy # Remote debugging
1
+ #ptvsd # Remote debugging
2
2
  #wsgi-lineprof # Profiling
@@ -7,9 +7,7 @@ const babelPresets = [
7
7
  [
8
8
  require.resolve('@babel/preset-env'),
9
9
  {
10
- targets: {
11
- browsers: ['> 0.7% in CH', '> 0.7% in FR', 'Firefox ESR'],
12
- },
10
+ targets: 'defaults, > 0.1% in CH, > 0.1% in FR, Firefox ESR and supports es6-class and not iOS < 10',
13
11
  modules: false,
14
12
  loose: true,
15
13
  },
@@ -32,7 +30,11 @@ module.exports = (env, argv) => {
32
30
  presets: babelPresets,
33
31
  babelrc: false,
34
32
  comments: false,
35
- plugins: [require.resolve('babel-plugin-angularjs-annotate')],
33
+ plugins: [
34
+ require.resolve('babel-plugin-angularjs-annotate'),
35
+ require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
36
+ require.resolve('@babel/plugin-proposal-optional-chaining'),
37
+ ],
36
38
  },
37
39
  },
38
40
  },
@@ -34,9 +34,7 @@ const babelPresets = [
34
34
  [
35
35
  require.resolve('@babel/preset-env'),
36
36
  {
37
- targets: {
38
- browsers: ['> 0.7% in CH', '> 0.7% in FR', 'Firefox ESR'],
39
- },
37
+ targets: 'defaults, > 0.1% in CH, > 0.1% in FR, Firefox ESR and supports es6-class and not iOS < 10',
40
38
  modules: false,
41
39
  loose: true,
42
40
  },
@@ -5,6 +5,7 @@ const config = commons({
5
5
  DllReferencePluginOptions: {
6
6
  context: '/usr/lib/',
7
7
  },
8
+ browsers: 'defaults, > 0.1% in CH, > 0.1% in FR, Firefox ESR and supports es6-class and not iOS < 10',
8
9
  });
9
10
 
10
11
  for (const plugin of config.plugins) {
@@ -1,11 +1,9 @@
1
- import distutils.core
2
-
3
1
  from pyramid.config import Configurator
4
2
 
5
3
  import {{cookiecutter.package}}_geoportal.authentication
6
4
  import {{cookiecutter.package}}_geoportal.dev
7
5
  import {{cookiecutter.package}}_geoportal.multi_organization
8
- from c2cgeoportal_geoportal import INTERFACE_TYPE_NGEO, add_interface_config, locale_negotiator
6
+ from c2cgeoportal_geoportal import add_interface_config, locale_negotiator
9
7
  from c2cgeoportal_geoportal.lib.i18n import LOCALE_PATH
10
8
  from {{cookiecutter.package}}_geoportal.resources import Root
11
9
 
@@ -28,10 +26,7 @@ def main(global_config, **settings):
28
26
 
29
27
  config.add_translation_dirs(LOCALE_PATH)
30
28
 
31
- # Workaround to not have the error: distutils.errors.DistutilsArgError: no commands supplied
32
- distutils.core._setup_stop_after = "config" # pylint: disable=protected-access
33
29
  config.include("c2cgeoportal_geoportal")
34
- distutils.core._setup_stop_after = None # pylint: disable=protected-access
35
30
 
36
31
  config.include({{cookiecutter.package}}_geoportal.multi_organization.includeme)
37
32
 
@@ -43,32 +43,12 @@ VALIDATE_PY_FOLDERS = admin/$(PACKAGE)_admin \
43
43
  $(PACKAGE)_geoportal/scripts $(PACKAGE)_geoportal/views
44
44
  VALIDATE_PY_TEST_FOLDERS = $(PACKAGE)_geoportal/tests
45
45
 
46
- PY_FILES = $(shell find $(PACKAGE) -type f -name '*.py' -print 2> /dev/null)
47
-
48
- # Templates
49
-
50
-
51
46
  # Disabling Make built-in rules to speed up execution time
52
47
  .SUFFIXES:
53
48
 
54
49
  .PHONY: build
55
50
  build: $(BUILD_RULES)
56
51
 
57
- .PHONY: checks
58
- checks: prospector eslint
59
-
60
- .PHONY: prospector
61
- prospector:
62
- prospector
63
-
64
- .PHONY: eslint
65
- eslint: $(APP_JS_FILES)
66
- eslint $?
67
-
68
- .PHONY: eslint-fix
69
- eslint-fix: $(APP_JS_FILES)
70
- eslint --fix $?
71
-
72
52
  # Server localisation
73
53
 
74
54
  PO_FILES = $(addprefix $(PACKAGE)_geoportal/locale/, $(addsuffix /LC_MESSAGES/$(PACKAGE)_geoportal-server.po, $(LANGUAGES)))
@@ -5,12 +5,9 @@ on:
5
5
  push:
6
6
 
7
7
  # To publish the images to be used on Kubernetes
8
- #env:
9
- # PROJECT: {{cookiecutter.package}}
10
- # HAS_SECRETS: ${{'{{'}} secrets.HAS_SECRETS }}
11
- # # Requires CI_GPG_PRIVATE_KEY and GOPASS_CI_GITHUB_TOKEN secrets.
12
- # # The release branches
13
- # HELM_RELEASE_NAMES: int-{{cookiecutter.geomapfish_main_version_dash}},prod-{{cookiecutter.geomapfish_main_version_dash}}
8
+ # env:
9
+ # PROJECT: {{cookiecutter.package}}
10
+ # HAS_SECRETS: ${{'{{'}} secrets.HAS_SECRETS }}
14
11
 
15
12
  jobs:
16
13
  main:
@@ -32,11 +29,28 @@ jobs:
32
29
  - run: echo "${HOME}/.local/bin" >> ${GITHUB_PATH}
33
30
  - run: python3 -m pip install --user --requirement=ci/requirements.txt
34
31
 
32
+ # Can be used to have some secrets (with mask)
33
+ # - run: make secrets
34
+ # - run: cat env.secrets |grep '^[# A-Z0-9_]\+='|sed -e 's/^[# A-Z0-9_]\+=\(.*\)/::add-mask::\1/g'
35
+
35
36
  - name: Checks
36
37
  run: c2cciutils-checks
37
38
 
39
+ # - name: Initialize the acceptance tests
40
+ # run: make acceptance-init
41
+ # - run: c2cciutils-docker-logs
42
+ # if: always()
43
+
44
+ # - name: Run the acceptance tests
45
+ # run: make acceptance
46
+ # - run: c2cciutils-docker-logs
47
+ # if: always()
48
+
38
49
  - name: Build
39
- run: ./build --docker-compose-version-2
50
+ run: ./build
51
+
52
+ - name: Application checks
53
+ run: make checks
40
54
 
41
55
  # To publish the images to be used on Kubernetes
42
56
  # - name: Publish
@@ -40,7 +40,7 @@ jobs:
40
40
  - run: python3 -m pip install --user --requirement=ci/requirements.txt
41
41
 
42
42
  - name: Build
43
- run: ./build --docker-compose-version-2
43
+ run: ./build
44
44
 
45
45
  - name: Publish
46
46
  run: c2cciutils-publish --branch=${{'{{'}} matrix.branch }} --type=rebuild
@@ -7,7 +7,7 @@ on:
7
7
 
8
8
  jobs:
9
9
  l10n:
10
- runs-on: ubuntu-18.04
10
+ runs-on: ubuntu-22.04
11
11
  name: Update l10n cron job
12
12
  timeout-minutes: 10
13
13
 
@@ -59,6 +59,7 @@ jobs:
59
59
  'Authorization': 'Bearer ${{'{{'}} secrets.GOPASS_CI_GITHUB_TOKEN {{'}}'}}',
60
60
  'Content-Type': 'application/json',
61
61
  },
62
+ timeout=120,
62
63
  )
63
64
  # 422 is the return code when the pull request already exists
64
65
  assert response.status_code < 300 or response.status_code == 422, f'{response.status_code} - {response.text}'"
@@ -14,7 +14,7 @@ ENV CONFIG_VARS sqlalchemy.url sqlalchemy.pool_recycle sqlalchemy.pool_size sqla
14
14
  dbsessions urllogin host_forward_host headers_whitelist headers_blacklist \
15
15
  smtp c2c.base_path welcome_email \
16
16
  lingua_extractor interfaces_config interfaces devserver_url api authentication intranet metrics pdfreport \
17
- vector_tiles i18next
17
+ vector_tiles i18next main_ogc_server
18
18
 
19
19
  COPY . /tmp/config/
20
20
 
@@ -27,14 +27,14 @@ ARG PGSCHEMA
27
27
  ENV PGSCHEMA=$PGSCHEMA
28
28
 
29
29
  RUN \
30
- cd /tmp/config/geoportal/ && \
31
- c2c-template --vars ${VARS_FILE} \
30
+ cd /tmp/config/geoportal/ \
31
+ && c2c-template --vars ${VARS_FILE} \
32
32
  --get-config {{cookiecutter.package}}_geoportal/config.yaml \
33
- ${CONFIG_VARS} && \
34
- pykwalify --data-file {{cookiecutter.package}}_geoportal/config.yaml \
35
- --schema-file CONST_config-schema.yaml && \
36
- rm CONST_* vars.yaml && \
37
- qgisserver-plugin-config {{cookiecutter.package}}_geoportal/config.yaml ../qgisserver/geomapfish.yaml.tmpl
33
+ ${CONFIG_VARS} \
34
+ && pykwalify --data-file {{cookiecutter.package}}_geoportal/config.yaml \
35
+ --schema-file CONST_config-schema.yaml \
36
+ && rm CONST_* vars.yaml \
37
+ && qgisserver-plugin-config {{cookiecutter.package}}_geoportal/config.yaml ../qgisserver/geomapfish.yaml.tmpl
38
38
 
39
39
  ###############################################################################
40
40
 
@@ -46,26 +46,26 @@ ENV PGSCHEMA=$PGSCHEMA
46
46
  COPY --from=builder /tmp/config/ /tmp/config/
47
47
 
48
48
  RUN \
49
- if [ -e /tmp/config/mapserver ]; then mv /tmp/config/mapserver /etc/; fi && \
50
- if [ -e /tmp/config/tilegeneration ]; then mv /tmp/config/tilegeneration /etc/; fi && \
51
- if [ -e /tmp/config/qgisserver ]; then mv /tmp/config/qgisserver /etc/qgisserver; fi && \
52
- if [ -e /tmp/config/haproxy ]; then mv /tmp/config/haproxy/* /etc/haproxy/; fi && \
53
- mkdir --parent /usr/local/tomcat/webapps/ROOT/ && \
54
- if [ -e /tmp/config/print ]; then mv /tmp/config/print/print-apps /usr/local/tomcat/webapps/ROOT/; fi && \
55
- mv /tmp/config/geoportal/{{cookiecutter.package}}_geoportal/ /etc/geomapfish/ && \
56
- mv /tmp/config/geoportal/* /etc/geomapfish/ || true && \
57
- chmod g+w -R \
49
+ mvif /tmp/config/mapserver /etc/ \
50
+ && mvif /tmp/config/tilegeneration /etc/ \
51
+ && mvif /tmp/config/qgisserver /etc/qgisserver \
52
+ && mvif /tmp/config/haproxy/* /etc/haproxy/ \
53
+ && mkdir --parent /usr/local/tomcat/webapps/ROOT/ \
54
+ && mvif /tmp/config/print /tmp/config/print/print-apps /usr/local/tomcat/webapps/ROOT/ \
55
+ && mv /tmp/config/geoportal/{{cookiecutter.package}}_geoportal/ /etc/geomapfish/ \
56
+ && mv /tmp/config/geoportal/* /etc/geomapfish/ || true \
57
+ && chmod g+w -R \
58
58
  /etc/geomapfish \
59
59
  /etc/mapserver \
60
60
  /etc/qgisserver \
61
61
  /etc/tilegeneration \
62
62
  /usr/local/tomcat/webapps/ROOT/print-apps \
63
63
  /etc/haproxy_dev \
64
- /etc/haproxy && \
65
- adduser www-data root && \
66
- sed 's#bind :80#bind *:443 ssl crt /etc/haproxy_dev/localhost.pem#g' /etc/haproxy/haproxy.cfg.tmpl \
67
- > /etc/haproxy_dev/haproxy.cfg.tmpl && \
68
- echo ' http-request set-header X-Forwarded-Proto https' >> /etc/haproxy_dev/haproxy.cfg.tmpl
64
+ /etc/haproxy \
65
+ && adduser www-data root \
66
+ && sed 's#bind :80#bind *:443 ssl crt /etc/haproxy_dev/localhost.pem#g' /etc/haproxy/haproxy.cfg.tmpl \
67
+ > /etc/haproxy_dev/haproxy.cfg.tmpl \
68
+ && echo ' http-request set-header X-Forwarded-Proto https' >> /etc/haproxy_dev/haproxy.cfg.tmpl
69
69
 
70
70
  VOLUME /etc/geomapfish \
71
71
  /etc/mapserver \
@@ -1,7 +1,16 @@
1
1
  PROJECT_PUBLIC_URL=https://example.camptocamp.com/
2
+ DUMP_FILE=dump.backup
2
3
  PACKAGE={{cookiecutter.package}}
3
4
  LANGUAGES=en fr de it
4
5
 
6
+ .PHONY: help
7
+ help: ## Display this help message
8
+ @echo "Usage: make <target>"
9
+ @echo
10
+ @echo "Available targets:"
11
+ @grep --extended-regexp --no-filename '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | sort | \
12
+ awk 'BEGIN {FS = ":.*?## "}; {printf " %-20s%s\n", $$1, $$2}'
13
+
5
14
  .PHONY: update-po-from-url
6
15
  update-po-from-url: ## Update the po files from the URL provide by PROJECT_PUBLIC_URL
7
16
  curl --fail --retry 5 --retry-delay 1 \
@@ -10,5 +19,52 @@ update-po-from-url: ## Update the po files from the URL provide by PROJECT_PUBLI
10
19
  docker-compose run --rm -T tools update-po-only `id --user` `id --group` $(LANGUAGES)
11
20
 
12
21
  .PHONY: update-po
13
- update-po:
14
- docker-compose exec -T tools sh -c "USER_ID=`id --user` GROUP_ID=`id --group` make -C geoportal update-po"
22
+ update-po: ## Update the po files from the running composition
23
+ docker-compose exec -T tools sh -c "USER_ID=`id --user` GROUP_ID=`id --group` make --directory=geoportal update-po"
24
+
25
+ .PHONY: checks
26
+ checks: prospector eslint ## Runs the checks
27
+
28
+ .PHONY: prospector
29
+ prospector: ## Runs the Prospector checks
30
+ docker-compose run --entrypoint= --no-deps --rm --volume=$(CURDIR)/geoportal:/app geoportal \
31
+ prospector --output-format=pylint --die-on-tool-error
32
+
33
+ .PHONY: eslint
34
+ eslint: ## Runs the eslint checks
35
+ docker-compose run --entrypoint= --no-deps --rm --volume=$(CURDIR)/geoportal:/app geoportal \
36
+ eslint $(find {{cookiecutter.package}} -type f -name '*.js' -print 2> /dev/null)
37
+ docker-compose run --entrypoint= --no-deps --rm --volume=$(CURDIR)/geoportal:/app geoportal \
38
+ eslint $(find {{cookiecutter.package}} -type f -name '*.ts' -print 2> /dev/null)
39
+
40
+ .PHONY: qgis
41
+ qgis: ## Run QGIS desktop
42
+ docker-compose -f docker-compose.yaml -f docker-compose-qgis.yaml run --rm qgis
43
+
44
+ secrets.tar.bz2.gpg: env.secrets ## Encrypt the secrets for committing changes
45
+ tar -jcf secrets.tar.bz2 $^
46
+ rm -f $@
47
+ gpg --symmetric --cipher-algo AES256 --batch \
48
+ --passphrase=$(shell gopass show gs/ci/large-secret-passphrase) secrets.tar.bz2
49
+ rm secrets.tar.bz2
50
+
51
+ .PHONY: secrets
52
+ secrets: ## Decrypt the secrets.tar.bz2.gpg file
53
+ gpg --quiet --batch --yes --decrypt --passphrase=$(shell gopass show gs/ci/large-secret-passphrase) \
54
+ --output secrets.tar.bz2 secrets.tar.bz2.gpg
55
+ tar --touch -jxf secrets.tar.bz2
56
+ rm secrets.tar.bz2
57
+
58
+ .PHONY: acceptance-init
59
+ acceptance-init: ## Initialize the acceptance tests
60
+ docker-compose --file=docker-compose.yaml --file=docker-compose-db.yaml up -d db tools
61
+ docker-compose exec -T tools wait-db
62
+ docker-compose exec -T tools psql --command="DROP EXTENSION IF EXISTS postgis CASCADE"
63
+ scripts/db-restore --docker-compose-file=docker-compose.yaml --docker-compose-file=docker-compose-db.yaml \
64
+ --arg=--clean --arg=--if-exists --arg=--verbose $(DUMP_FILE)
65
+ docker-compose --file=docker-compose.yaml --file=docker-compose-db.yaml up -d
66
+
67
+ .PHONY: acceptance
68
+ acceptance: ## Run the acceptance tests
69
+ docker-compose exec -T tools pytest -vv tests/
70
+ ci/docker-compose-check
@@ -5,26 +5,42 @@ import os
5
5
  import os.path
6
6
  import platform
7
7
  import re
8
+ import shlex
8
9
  import shutil
9
10
  import stat
10
11
  import subprocess
11
12
  import sys
12
13
  import urllib.request
13
- from typing import Any, Dict, List, Optional
14
+ from typing import TYPE_CHECKING, Any, List, Optional
14
15
 
15
16
  import yaml
16
17
 
18
+ CompletedProcess = subprocess.CompletedProcess[str] if TYPE_CHECKING else subprocess.CompletedProcess
17
19
 
18
- def run(args: argparse.Namespace, command: List[str], **kwargs: Any) -> None:
20
+
21
+ def run(
22
+ args: argparse.Namespace, command: List[str], exit_on_error: bool = True, **kwargs: Any
23
+ ) -> Optional[CompletedProcess]:
19
24
  if args.verbose or args.dry_run:
20
- print(" ".join(command))
21
- if not args.dry_run:
22
- subprocess.run(command, **kwargs) # nosec
25
+ print(" ".join([shlex.quote(c) for c in command]))
26
+ if not args.dry_run or "stdout" in kwargs:
27
+ if args.stack_trace and exit_on_error and not "checks" in kwargs:
28
+ kwargs["check"] = True
29
+ process = subprocess.run(command, **kwargs) # nosec
30
+ if exit_on_error and process.returncode != 0:
31
+ print(
32
+ "An error occurred during execution of `{}`".format(
33
+ " ".join([shlex.quote(c) for c in command])
34
+ )
35
+ )
36
+ sys.exit(process.returncode)
37
+ return process
38
+ return None
23
39
 
24
40
 
25
41
  def main() -> None:
26
42
  parser = argparse.ArgumentParser(description="Build the project")
27
- parser.add_argument("--verbose", action="store_true", help="Display the docker build commands")
43
+ parser.add_argument("--verbose", action="store_true", help="Display the Docker build commands")
28
44
  parser.add_argument(
29
45
  "--dry-run", action="store_true", help="Display the docker build commands without executing them"
30
46
  )
@@ -34,9 +50,11 @@ def main() -> None:
34
50
  parser.add_argument("--not-simple", action="store_true", help="Force not simple application mode")
35
51
  parser.add_argument("--upgrade", help="Start upgrading the project to version")
36
52
  parser.add_argument(
37
- "--fast-reload",
38
- action="store_true",
39
- help="Restart the composition without Redis to don't lost the cache",
53
+ "--reload",
54
+ nargs="?",
55
+ action="store",
56
+ const="",
57
+ help="Comma separate list of services that will be reloaded after the build",
40
58
  )
41
59
  parser.add_argument(
42
60
  "--no-pull",
@@ -47,9 +65,7 @@ def main() -> None:
47
65
  parser.add_argument(
48
66
  "--debug", help="Path to c2cgeoportal source folder to be able to debug the upgrade procedure"
49
67
  )
50
- parser.add_argument(
51
- "--docker-compose-version-2", action="store_true", help="Use Docker Compose version 2"
52
- )
68
+ parser.add_argument("--stack-trace", action="store_true", help="Display the stack trace on error")
53
69
  parser.add_argument("env_files", nargs="*", help="The environment config")
54
70
  args = parser.parse_args()
55
71
 
@@ -61,7 +77,7 @@ def main() -> None:
61
77
  match = re.match(r"^([0-9]+\.[0-9]+)\.[0-9a-z]+\.[0-9]+$", args.upgrade)
62
78
  if match is not None:
63
79
  major_version = match.group(1)
64
- full_version = args.upgrade if args.upgrade != "master" else "latest"
80
+ full_version = args.upgrade
65
81
  with open("upgrade", "w", encoding="utf-8") as f:
66
82
  with urllib.request.urlopen( # nosec
67
83
  "https://raw.githubusercontent.com/camptocamp/c2cgeoportal/{major_version}/scripts/upgrade".format(
@@ -80,9 +96,9 @@ def main() -> None:
80
96
  os.chmod("upgrade", os.stat("upgrade").st_mode | stat.S_IXUSR)
81
97
  try:
82
98
  if platform.system() == "Windows":
83
- run(args, ["python", "upgrade", full_version] + debug_args, check=True)
99
+ run(args, ["python", "upgrade", full_version] + debug_args)
84
100
  else:
85
- run(args, ["./upgrade", full_version] + debug_args, check=True)
101
+ run(args, ["./upgrade", full_version] + debug_args)
86
102
  except subprocess.CalledProcessError:
87
103
  sys.exit(1)
88
104
  sys.exit(0)
@@ -110,25 +126,20 @@ def main() -> None:
110
126
  if args.not_simple:
111
127
  simple = False
112
128
 
113
- git_hash = (
114
- subprocess.run(["git", "rev-parse", "HEAD"], check=True, stdout=subprocess.PIPE)
115
- .stdout.strip()
116
- .decode()
117
- )
129
+ git_hash = run(args, ["git", "rev-parse", "HEAD"], stdout=subprocess.PIPE).stdout.decode().strip()
118
130
 
119
131
  dest.write("SIMPLE={}\n".format(str(simple).upper()))
120
132
  dest.write("GIT_HASH={git_hash}\n".format(git_hash=git_hash))
121
133
 
122
134
  dest.write("# Used env files: {}\n".format(", ".join(env_files)))
123
135
 
124
- docker_compose = ["docker", "compose"] if args.docker_compose_version_2 else ["docker-compose"]
125
136
  if not args.env:
126
- docker_compose_build_cmd = [*docker_compose, "build"]
137
+ docker_compose_build_cmd = ["docker-compose", "build"]
127
138
 
128
139
  if not args.no_pull:
129
140
  # Pull all the images
130
141
  if not args.service:
131
- run(args, [*docker_compose, "pull", "--ignore-pull-failures"], check=True) # nosec
142
+ run(args, ["docker-compose", "pull", "--ignore-pull-failures"]) # nosec
132
143
  docker_compose_build_cmd.append("--pull")
133
144
 
134
145
  if args.service:
@@ -138,24 +149,33 @@ def main() -> None:
138
149
  print_args = [a.replace('"', '\\"') for a in print_args]
139
150
  print_args = [a.replace("'", "\\'") for a in print_args]
140
151
  try:
141
- run(args, docker_compose_build_cmd, check=True) # nosec
152
+ env = {"DOCKER_BUILDKIT": "1", "COMPOSE_DOCKER_CLI_BUILD": "1"}
153
+ env.update(os.environ)
154
+ run(args, docker_compose_build_cmd, env=env) # nosec
142
155
  except subprocess.CalledProcessError as e:
143
156
  print("Error with command: " + " ".join(print_args))
144
157
  sys.exit(e.returncode)
145
158
 
146
- if args.fast_reload:
159
+ if args.reload:
160
+ services = args.reload.split(",")
161
+ elif args.reload == "":
147
162
  services = [
148
163
  service
149
- for service in subprocess.run(
150
- [*docker_compose, "ps", "--services", "--all"], stdout=subprocess.PIPE, check=True
164
+ for service in run(
165
+ args,
166
+ ["docker-compose", "ps", "--services", "--all"],
167
+ stdout=subprocess.PIPE,
168
+ exit_on_error=True,
151
169
  )
152
170
  .stdout.decode()
153
171
  .splitlines()
154
172
  if not service.startswith("redis")
155
173
  ]
156
174
 
157
- run(args, [*docker_compose, "rm", "--stop", "--force"] + services, check=True)
158
- run(args, [*docker_compose, "up", "-d"], check=True)
175
+ if args.reload is not None:
176
+ run(args, ["docker-compose", "rm", "--force", "-v", "config"])
177
+ for service in services:
178
+ run(args, ["docker-compose", "up", "--detach", "--force-recreate", service])
159
179
 
160
180
 
161
181
  if __name__ == "__main__":
@@ -1,11 +1,7 @@
1
- # yaml-language-server: $schema=https://raw.githubusercontent.com/camptocamp/c2cciutils/master/c2cciutils/schema.json
1
+ # yaml-language-server: $schema=https://raw.githubusercontent.com/camptocamp/c2cciutils/1.4/c2cciutils/schema.json
2
2
 
3
3
  checks:
4
- black: False
5
- isort: False
6
- prettier: False
7
4
  codespell: False
8
- eof: False
9
5
  required_workflows: False
10
6
  dependabot_config: False
11
7
  prospector_config: False
@@ -21,5 +17,6 @@ version:
21
17
  publish:
22
18
  pypi: false
23
19
  docker:
20
+ dispatch: {}
24
21
  images:
25
22
  - name: camptocamp/{{cookiecutter.package}}-config
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import argparse
4
+ import subprocess
5
+ import sys
6
+
7
+
8
+ def _main() -> None:
9
+ argparser = argparse.ArgumentParser("Tests that's all the services are running")
10
+ argparser.parse_args()
11
+
12
+ services = [
13
+ s.strip()
14
+ for s in subprocess.run(["docker-compose", "ps"], check=True, stdout=subprocess.PIPE)
15
+ .stdout.decode("utf-8")
16
+ .splitlines()
17
+ ]
18
+ errors_statuses = [s for s in services if " Exit " in s and not s.endswith(" Exit 0")]
19
+ if errors_statuses:
20
+ print("\n".join(errors_statuses))
21
+ sys.exit(1)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ _main()