Kaynağa Gözat

Merge branch 'feat/g2g-nextjs' into feat/ui-admin-g2g-transfer-advanced-options

Taichi Masuyama 3 yıl önce
ebeveyn
işleme
5d3c3cab55
28 değiştirilmiş dosya ile 1147 ekleme ve 136 silme
  1. 53 34
      .github/workflows/release-rc.yml
  2. 63 37
      .github/workflows/release.yml
  3. 56 0
      .github/workflows/reusable-app-build-image.yml
  4. 52 0
      .github/workflows/reusable-app-create-manifests.yml
  5. 5 0
      .gitignore
  6. 0 1
      packages/app/.env.development
  7. 5 5
      packages/app/docker/Dockerfile
  8. 65 0
      packages/app/docker/codebuild/.terraform.lock.hcl
  9. 32 0
      packages/app/docker/codebuild/buildspec.yml
  10. 25 0
      packages/app/docker/codebuild/codebuild.tf
  11. 15 0
      packages/app/docker/codebuild/main.tf
  12. 26 0
      packages/app/docker/codebuild/oidc.tf
  13. 15 0
      packages/app/docker/codebuild/secretsmanager.tf
  14. 663 0
      packages/app/docker/codebuild/terraform.tfstate
  15. 0 6
      packages/app/docker/nocdn/.env.production.local
  16. 2 2
      packages/app/public/static/locales/en_US/admin.json
  17. 1 1
      packages/app/public/static/locales/en_US/commons.json
  18. 2 2
      packages/app/public/static/locales/zh_CN/admin.json
  19. 6 0
      packages/app/src/components/Admin/G2GDataTransferStatusIcon.tsx
  20. 1 0
      packages/app/src/interfaces/g2g-transfer.ts
  21. 0 1
      packages/app/src/server/models/config.ts
  22. 8 8
      packages/app/src/server/routes/apiv3/g2g-transfer.ts
  23. 3 3
      packages/app/src/server/routes/apiv3/import.js
  24. 0 6
      packages/app/src/server/service/config-loader.ts
  25. 1 1
      packages/app/src/server/service/export.js
  26. 44 25
      packages/app/src/server/service/g2g-transfer.ts
  27. 2 2
      packages/app/src/server/service/import.js
  28. 2 2
      packages/app/src/server/util/createGrowiPagesFromImports.js

+ 53 - 34
.github/workflows/release-rc.yml

@@ -5,60 +5,79 @@ on:
     branches:
     branches:
       - rc/**
       - rc/**
 
 
-jobs:
 
 
-  build-rc:
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+
+jobs:
 
 
+  determine-tags:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
 
 
-    strategy:
-      matrix:
-        platform: [linux/amd64, linux/arm64]
+    outputs:
+      TAGS: ${{ steps.meta.outputs.tags }}
+      TAGS_GHCR: ${{ steps.meta-ghcr.outputs.tags }}
 
 
     steps:
     steps:
     - uses: actions/checkout@v3
     - uses: actions/checkout@v3
-      with:
-        lfs: true
 
 
     - name: Retrieve information from package.json
     - name: Retrieve information from package.json
       uses: myrotvorets/info-from-package-json-action@1.2.0
       uses: myrotvorets/info-from-package-json-action@1.2.0
       id: package-json
       id: package-json
 
 
-    - name: Docker meta
+    - name: Docker meta for docker.io
+      uses: docker/metadata-action@v4
       id: meta
       id: meta
+      with:
+        images: docker.io/weseek/growi
+        sep-tags: ','
+        tags: |
+          type=raw,value=${{ steps.package-json.outputs.packageVersion }}
+          type=raw,value=${{ steps.package-json.outputs.packageVersion }}.{{sha}}
+
+    - name: Docker meta for ghcr.io
       uses: docker/metadata-action@v4
       uses: docker/metadata-action@v4
+      id: meta-ghcr
       with:
       with:
-        images: weseek/growi,ghcr.io/weseek/growi
+        images: ghcr.io/weseek/growi
+        sep-tags: ','
         tags: |
         tags: |
           type=raw,value=${{ steps.package-json.outputs.packageVersion }}
           type=raw,value=${{ steps.package-json.outputs.packageVersion }}
           type=raw,value=${{ steps.package-json.outputs.packageVersion }}.{{sha}}
           type=raw,value=${{ steps.package-json.outputs.packageVersion }}.{{sha}}
 
 
-    - name: Login to docker.io registry
-      run: |
-        echo ${{ secrets. DOCKER_REGISTRY_PASSWORD }} | docker login --username wsmoogle --password-stdin
 
 
-    - name: Login to GitHub Container Registry
-      uses: docker/login-action@v2
-      with:
-        registry: ghcr.io
-        username: wsmoogle
-        password: ${{ secrets.DOCKER_REGISTRY_ON_GITHUB_PASSWORD }}
+  build-image-rc:
+    uses: weseek/growi/.github/workflows/reusable-app-build-image.yml@master
+    with:
+      image-name: weseek/growi
+      tag-temporary: latest-rc
+    secrets:
+      AWS_ROLE_TO_ASSUME_FOR_OIDC: ${{ secrets.AWS_ROLE_TO_ASSUME_FOR_OIDC }}
 
 
-    - name: Set up QEMU
-      if: ${{ matrix.platform == 'linux/arm64' }}
-      uses: docker/setup-qemu-action@v1
 
 
-    - name: Set up Docker Buildx
-      uses: docker/setup-buildx-action@v2
+  publish-image-rc:
+    needs: [determine-tags, build-image-rc]
+
+    uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master
+    with:
+      tags: ${{ needs.determine-tags.outputs.TAGS }}
+      registry: docker.io
+      image-name: weseek/growi
+      tag-temporary: latest-rc
+    secrets:
+      DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
+
+  publish-image-rc-ghcr:
+    needs: [determine-tags, build-image-rc]
+
+    uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master
+    with:
+      tags: ${{ needs.determine-tags.outputs.TAGS_GHCR }}
+      registry: ghcr.io
+      image-name: weseek/growi
+      tag-temporary: latest-rc
+    secrets:
+      DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_ON_GITHUB_PASSWORD }}
 
 
-    - name: Build and push
-      uses: docker/build-push-action@v2
-      with:
-        context: .
-        file: ./packages/app/docker/Dockerfile
-        platforms: ${{ matrix.platform }}
-        push: true
-        builder: ${{ steps.buildx.outputs.name }}
-        cache-from: type=gha
-        cache-to: type=gha,mode=max
-        tags: ${{ steps.meta.outputs.tags }}

+ 63 - 37
.github/workflows/release.yml

@@ -121,63 +121,90 @@ jobs:
         github_token: ${{ secrets.GITHUB_TOKEN }}
         github_token: ${{ secrets.GITHUB_TOKEN }}
 
 
 
 
-  build-image:
+  determine-tags:
     needs: create-github-release
     needs: create-github-release
-
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
 
 
-    strategy:
-      matrix:
-        platform: [linux/amd64, linux/arm64]
+    outputs:
+      TAGS: ${{ steps.meta.outputs.tags }}
+      TAGS_GHCR: ${{ steps.meta-ghcr.outputs.tags }}
 
 
     steps:
     steps:
     - uses: actions/checkout@v3
     - uses: actions/checkout@v3
-      with:
-        ref: v${{ needs.create-github-release.outputs.RELEASED_VERSION }}
-        lfs: true
 
 
-    - name: Docker meta
-      id: meta
+    - name: Retrieve information from package.json
+      uses: myrotvorets/info-from-package-json-action@1.2.0
+      id: package-json
+
+    - name: Docker meta for docker.io
       uses: docker/metadata-action@v4
       uses: docker/metadata-action@v4
+      id: meta
       with:
       with:
-        images: weseek/growi,ghcr.io/weseek/growi
+        images: docker.io/weseek/growi
+        sep-tags: ','
         tags: |
         tags: |
           type=raw,value=latest
           type=raw,value=latest
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}.{{patch}}
           type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}.{{patch}}
 
 
-    - name: Login to Docker Hub
-      uses: docker/login-action@v2
+    - name: Docker meta for ghcr.io
+      uses: docker/metadata-action@v4
+      id: meta-ghcr
       with:
       with:
-        username: wsmoogle
-        password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
+        images: ghcr.io/weseek/growi
+        sep-tags: ','
+        tags: |
+          type=raw,value=latest
+          type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}
+          type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}
+          type=semver,value=${{ needs.create-github-release.outputs.RELEASED_VERSION }},pattern={{major}}.{{minor}}.{{patch}}
 
 
-    - name: Login to GitHub Container Registry
-      uses: docker/login-action@v2
-      with:
-        registry: ghcr.io
-        username: wsmoogle
-        password: ${{ secrets.DOCKER_REGISTRY_ON_GITHUB_PASSWORD }}
 
 
-    - name: Set up QEMU
-      if: ${{ matrix.platform == 'linux/arm64' }}
-      uses: docker/setup-qemu-action@v1
+  build-image:
+    needs: create-github-release
 
 
-    - name: Set up Docker Buildx
-      uses: docker/setup-buildx-action@v2
+    uses: weseek/growi/.github/workflows/reusable-app-build-image.yml@master
+    with:
+      source-version: refs/tags/v${{ needs.create-github-release.outputs.RELEASED_VERSION }}
+      image-name: weseek/growi
+      tag-temporary: latest
+    secrets:
+      AWS_ROLE_TO_ASSUME_FOR_OIDC: ${{ secrets.AWS_ROLE_TO_ASSUME_FOR_OIDC }}
+
+
+  publish-image:
+    needs: [determine-tags, build-image]
+
+    uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master
+      tags: ${{ needs.determine-tags.outputs.TAGS }}
+      registry: docker.io
+      image-name: weseek/growi
+      tag-temporary: latest
+    secrets:
+      DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
+
+  publish-image-ghcr:
+    needs: [determine-tags, build-image]
+
+    uses: weseek/growi/.github/workflows/reusable-app-create-manifests.yml@master
+    with:
+      tags: ${{ needs.determine-tags.outputs.TAGS_GHCR }}
+      registry: ghcr.io
+      image-name: weseek/growi
+      tag-temporary: latest
+    secrets:
+      DOCKER_REGISTRY_PASSWORD: ${{ secrets.DOCKER_REGISTRY_ON_GITHUB_PASSWORD }}
+
+
+  post-publish:
+    needs: [create-github-release, publish-image, publish-image-ghcr]
+    runs-on: ubuntu-latest
 
 
-    - name: Build and push
-      uses: docker/build-push-action@v3
+    steps:
+    - uses: actions/checkout@v3
       with:
       with:
-        context: .
-        file: ./packages/app/docker/Dockerfile
-        platforms: ${{ matrix.platform }}
-        push: true
-        builder: ${{ steps.buildx.outputs.name }}
-        cache-from: type=gha
-        cache-to: type=gha,mode=max
-        tags: ${{ steps.meta.outputs.tags }}
+        ref: v${{ needs.create-github-release.outputs.RELEASED_VERSION }}
 
 
     - name: Update Docker Hub Description
     - name: Update Docker Hub Description
       uses: peter-evans/dockerhub-description@v3
       uses: peter-evans/dockerhub-description@v3
@@ -193,7 +220,6 @@ jobs:
         channel: '#release'
         channel: '#release'
         url: ${{ secrets.SLACK_WEBHOOK_URL }}
         url: ${{ secrets.SLACK_WEBHOOK_URL }}
         created_tag: 'v${{ needs.create-github-release.outputs.RELEASED_VERSION }}'
         created_tag: 'v${{ needs.create-github-release.outputs.RELEASED_VERSION }}'
-        message: '*Release v${{ needs.create-github-release.outputs.RELEASED_VERSION }} (${{ matrix.platform }})* Succeeded'
 
 
     - name: Check whether workspace is clean
     - name: Check whether workspace is clean
       run: |
       run: |

+ 56 - 0
.github/workflows/reusable-app-build-image.yml

@@ -0,0 +1,56 @@
+name: Reusable build app container image workflow
+
+on:
+  workflow_call:
+    inputs:
+      source-version:
+        type: string
+        default: ${{ github.sha }}
+      image-name:
+        type: string
+        default: weseek/growi
+      tag-temporary:
+        type: string
+        default: latest
+    secrets:
+      AWS_ROLE_TO_ASSUME_FOR_OIDC:
+        required: true
+
+
+
+jobs:
+
+  build-image:
+    runs-on: ubuntu-latest
+
+    # These permissions are needed to interact with GitHub's OIDC Token endpoint.
+    permissions:
+      id-token: write
+      contents: write
+
+    strategy:
+      matrix:
+        platform: [amd64, arm64]
+
+    steps:
+    - uses: actions/checkout@v3
+
+    - name: Configure AWS Credentials
+      uses: aws-actions/configure-aws-credentials@v1
+      with:
+        aws-region: ap-northeast-1
+        role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME_FOR_OIDC }}
+        role-session-name: SessionForReleaseGROWI-RC
+
+    - name: Run CodeBuild
+      uses: dark-mechanicum/aws-codebuild@v1
+      with:
+        projectName: growi-official-image-builder
+      env:
+        CODEBUILD__sourceVersion: ${{ inputs.source-version }}
+        CODEBUILD__imageOverride: ${{ (matrix.platform == 'amd64' && 'aws/codebuild/standard:6.0') || 'aws/codebuild/amazonlinux2-aarch64-standard:2.0' }}
+        CODEBUILD__environmentTypeOverride: ${{ (matrix.platform == 'amd64' && 'LINUX_CONTAINER') || 'ARM_CONTAINER' }}
+        CODEBUILD__environmentVariablesOverride: '[
+          { "name": "IMAGE_TAG", "type": "PLAINTEXT", "value": "docker.io/${{ inputs.image-name }}:${{ inputs.tag-temporary }}-${{ matrix.platform }}" },
+          { "name": "IMAGE_TAG_GHCR", "type": "PLAINTEXT", "value": "ghcr.io/${{ inputs.image-name }}:${{ inputs.tag-temporary }}-${{ matrix.platform }}" }
+        ]'

+ 52 - 0
.github/workflows/reusable-app-create-manifests.yml

@@ -0,0 +1,52 @@
+name: Reusable create app container image manifests workflow
+
+on:
+  workflow_call:
+    inputs:
+      tags:
+        type: string
+        required: true
+      registry:
+        type: string
+        default: 'docker.io'
+      image-name:
+        type: string
+        default: weseek/growi
+      tag-temporary:
+        type: string
+        default: latest
+    secrets:
+      DOCKER_REGISTRY_PASSWORD:
+        required: true
+
+
+
+jobs:
+
+  create-manifest:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: Docker meta for extra-images
+      id: meta-extra-images
+      uses: docker/metadata-action@v4
+      with:
+        images: ${{ inputs.registry }}/${{ inputs.image-name }}
+        sep-tags: ','
+        tags: |
+          type=raw,value=${{ inputs.tag-temporary }}-amd64
+          type=raw,value=${{ inputs.tag-temporary }}-arm64
+
+    - name: Login to Container Registry
+      uses: docker/login-action@v2
+      with:
+        registry: ${{ inputs.registry }}
+        username: wsmoogle
+        password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
+
+    - name: Create and push manifest images
+      uses: Noelware/docker-manifest-action@master
+      with:
+        base-image: ${{ inputs.tags }}
+        extra-images: ${{ steps.meta-extra-images.outputs.tags }}
+        push: true

+ 5 - 0
.gitignore

@@ -29,6 +29,11 @@ yarn-error.log*
 # typescript
 # typescript
 *.tsbuildinfo
 *.tsbuildinfo
 
 
+# Terraform
+**/.terraform/*
+# *.tfstate
+*.tfstate.*
+
 # IDE, dev #
 # IDE, dev #
 .idea
 .idea
 *.orig
 *.orig

+ 0 - 1
packages/app/.env.development

@@ -7,7 +7,6 @@ MIGRATIONS_DIR=src/migrations/
 APP_SITE_URL=http://localhost:3000
 APP_SITE_URL=http://localhost:3000
 FILE_UPLOAD=mongodb
 FILE_UPLOAD=mongodb
 # MONGO_GRIDFS_TOTAL_LIMIT=10485760
 # MONGO_GRIDFS_TOTAL_LIMIT=10485760
-# NO_CDN=true
 MONGO_URI="mongodb://mongo:27017/growi"
 MONGO_URI="mongodb://mongo:27017/growi"
 # REDIS_URI="http://redis:6379"
 # REDIS_URI="http://redis:6379"
 # NCHAN_URI="http://nchan"
 # NCHAN_URI="http://nchan"

+ 5 - 5
packages/app/docker/Dockerfile

@@ -95,16 +95,16 @@ WORKDIR ${optDir}
 # ignore eslint and stylelint
 # ignore eslint and stylelint
 COPY ["package.json", "lerna.json", "tsconfig.base.json", "./"]
 COPY ["package.json", "lerna.json", "tsconfig.base.json", "./"]
 # copy all related packages
 # copy all related packages
-COPY packages/app packages/app
-COPY packages/core packages/core
 COPY packages/codemirror-textlint packages/codemirror-textlint
 COPY packages/codemirror-textlint packages/codemirror-textlint
+COPY packages/preset-themes packages/preset-themes
 COPY packages/slack packages/slack
 COPY packages/slack packages/slack
-COPY packages/ui packages/ui
+COPY packages/hackmd packages/hackmd
 COPY packages/remark-drawio packages/remark-drawio
 COPY packages/remark-drawio packages/remark-drawio
 COPY packages/remark-growi-directive packages/remark-growi-directive
 COPY packages/remark-growi-directive packages/remark-growi-directive
 COPY packages/remark-lsx packages/remark-lsx
 COPY packages/remark-lsx packages/remark-lsx
-COPY packages/hackmd packages/hackmd
-COPY packages/preset-themes packages/preset-themes
+COPY packages/ui packages/ui
+COPY packages/core packages/core
+COPY packages/app packages/app
 
 
 # build
 # build
 RUN yarn lerna run build
 RUN yarn lerna run build

+ 65 - 0
packages/app/docker/codebuild/.terraform.lock.hcl

@@ -0,0 +1,65 @@
+# This file is maintained automatically by "terraform init".
+# Manual edits may be lost in future updates.
+
+provider "registry.terraform.io/hashicorp/aws" {
+  version     = "4.49.0"
+  constraints = "~> 4.16"
+  hashes = [
+    "h1:oOwWQpvQWd1uVP1axBz/TO6xzzLWoL982AY/MQfeF7I=",
+    "zh:09803937f00fdf2873eccf685eec7854408925cbf183c9b683df7c5825be463f",
+    "zh:2af1575e538fb0b669266f8d1385b17bfdaf17c521b6b6329baa1f2971fc4a4d",
+    "zh:3f71882b438cde3108fe68cfe2637839d3eed08157a9721bd97babf3912247a8",
+    "zh:577af1b38f5da8a9f29eebe5eebec9279d26e757cd03b0c8c59311f9ce8a859b",
+    "zh:60160d39094973beefb9b10cfd6aaa5b63a2e68c32445ecffcd1b101356e6f9b",
+    "zh:762656454722548baeccf35cbaa23b887976337e1ed321682df7390419fdf22d",
+    "zh:7f6d7887821659bf3bef815949077dc91ffcdb0d911644a887b6683b264a5ca6",
+    "zh:8f16a352cc903f8951fa4619c36233b3e66e27d724817b131f2035dd8896f524",
+    "zh:8f768f65e370366c8b91c00d01c9a6264fe26ea9ae1819f14bdcd12c066272bc",
+    "zh:95ad78c689a83c08ef7c3e544c3c9aca93ed528054aa77cc968ddd9efa3a1023",
+    "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
+    "zh:a47097ab6a4ca8302da82964303ffdd2310ed65e8f8524bfe4058816cf1addb7",
+    "zh:b66d820c70cd5fd628ffe882d2b97e76b969dca4e6827ac2ba0f8d3bc5d6e9c6",
+    "zh:b80f713a4f3e1355c3dd1600e9d08b9f15ed2370054ec792ad2c01f2541abe02",
+    "zh:ce065bc3962cb71fa7652562226b9d486f3d7fcb88285c1020ebe2f550e28641",
+  ]
+}
+
+provider "registry.terraform.io/hashicorp/random" {
+  version     = "3.4.3"
+  constraints = ">= 2.1.0"
+  hashes = [
+    "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=",
+    "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752",
+    "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b",
+    "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53",
+    "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+    "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3",
+    "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5",
+    "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda",
+    "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6",
+    "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1",
+    "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d",
+    "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8",
+    "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93",
+  ]
+}
+
+provider "registry.terraform.io/hashicorp/tls" {
+  version     = "4.0.4"
+  constraints = ">= 3.0.0"
+  hashes = [
+    "h1:pe9vq86dZZKCm+8k1RhzARwENslF3SXb9ErHbQfgjXU=",
+    "zh:23671ed83e1fcf79745534841e10291bbf34046b27d6e68a5d0aab77206f4a55",
+    "zh:45292421211ffd9e8e3eb3655677700e3c5047f71d8f7650d2ce30242335f848",
+    "zh:59fedb519f4433c0fdb1d58b27c210b27415fddd0cd73c5312530b4309c088be",
+    "zh:5a8eec2409a9ff7cd0758a9d818c74bcba92a240e6c5e54b99df68fff312bbd5",
+    "zh:5e6a4b39f3171f53292ab88058a59e64825f2b842760a4869e64dc1dc093d1fe",
+    "zh:810547d0bf9311d21c81cc306126d3547e7bd3f194fc295836acf164b9f8424e",
+    "zh:824a5f3617624243bed0259d7dd37d76017097dc3193dac669be342b90b2ab48",
+    "zh:9361ccc7048be5dcbc2fafe2d8216939765b3160bd52734f7a9fd917a39ecbd8",
+    "zh:aa02ea625aaf672e649296bce7580f62d724268189fe9ad7c1b36bb0fa12fa60",
+    "zh:c71b4cd40d6ec7815dfeefd57d88bc592c0c42f5e5858dcc88245d371b4b8b1e",
+    "zh:dabcd52f36b43d250a3d71ad7abfa07b5622c69068d989e60b79b2bb4f220316",
+    "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
+  ]
+}

+ 32 - 0
packages/app/docker/codebuild/buildspec.yml

@@ -0,0 +1,32 @@
+version: 0.2
+
+env:
+  variables:
+    DOCKER_BUILDKIT: 1
+    IMAGE_TAG: ''
+    IMAGE_TAG_GHCR: ''
+  secrets-manager:
+    DOCKER_REGISTRY_PASSWORD: growi/official-image-builder:DOCKER_REGISTRY_PASSWORD
+    DOCKER_REGISTRY_ON_GITHUB_PAT: growi/official-image-builder:DOCKER_REGISTRY_ON_GITHUB_PAT
+
+phases:
+  pre_build:
+    commands:
+      # login to docker.io
+      - echo ${DOCKER_REGISTRY_PASSWORD} | docker login --username wsmoogle --password-stdin
+      # login to ghcr.io
+      - echo ${DOCKER_REGISTRY_ON_GITHUB_PAT} | docker login ghcr.io --username wsmoogle --password-stdin
+  build:
+    commands:
+      - docker build -t ${IMAGE_TAG} -f ./packages/app/docker/Dockerfile .
+      - docker tag ${IMAGE_TAG} ${IMAGE_TAG_GHCR}
+
+  post_build:
+    commands:
+      - docker push $IMAGE_TAG
+      - docker push $IMAGE_TAG_GHCR
+
+cache:
+  paths:
+    - node_modules/**/*
+    - packages/*/node_modules/**/*

+ 25 - 0
packages/app/docker/codebuild/codebuild.tf

@@ -0,0 +1,25 @@
+module "codebuild" {
+  source = "cloudposse/codebuild/aws"
+
+  name                = "growi-official-image-builder"
+  description         = "The CodeBuild Project for GROWI official docker image"
+
+  artifact_type       = "NO_ARTIFACTS"
+
+  source_type         = "GITHUB"
+  source_location     = "https://github.com/weseek/growi.git"
+  source_version      = "refs/heads/master"
+  git_clone_depth     = 1
+
+  buildspec           = "packages/app/docker/codebuild/buildspec.yml"
+
+  # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
+  build_image         = "aws/codebuild/amazonlinux2-x86_64-standard:3.0"
+  build_compute_type  = "BUILD_GENERAL1_LARGE"
+
+  privileged_mode     = true
+
+  cache_type          = "LOCAL"
+  local_cache_modes   = ["LOCAL_DOCKER_LAYER_CACHE", "LOCAL_CUSTOM_CACHE"]
+
+}

+ 15 - 0
packages/app/docker/codebuild/main.tf

@@ -0,0 +1,15 @@
+terraform {
+  required_providers {
+    aws = {
+      source  = "hashicorp/aws"
+      version = "~> 4.16"
+    }
+  }
+
+  required_version = ">= 1.2.0"
+}
+
+provider "aws" {
+  profile = "weseek"
+  region  = "ap-northeast-1"
+}

+ 26 - 0
packages/app/docker/codebuild/oidc.tf

@@ -0,0 +1,26 @@
+module "oidc_github" {
+  source  = "unfunco/oidc-github/aws"
+
+  iam_role_name = "GitHubOIDC-for-growi"
+  iam_role_inline_policies = {
+    "inline_policy" : data.aws_iam_policy_document.policy_document.json
+  }
+
+  github_repositories = [
+    "weseek/growi",
+  ]
+}
+
+data "aws_iam_policy_document" "policy_document" {
+  statement {
+    actions   = [
+      "codebuild:StartBuild",
+      "codebuild:StopBuild",
+      "codebuild:RetryBuild",
+      "codebuild:BatchGetBuilds"
+    ]
+    resources = [
+      module.codebuild.project_arn
+    ]
+  }
+}

+ 15 - 0
packages/app/docker/codebuild/secretsmanager.tf

@@ -0,0 +1,15 @@
+resource "aws_secretsmanager_secret" "secret" {
+  name = "growi/official-image-builder"
+}
+
+resource "aws_secretsmanager_secret_version" "main" {
+  secret_id     = aws_secretsmanager_secret.secret.id
+  secret_string = jsonencode({
+    KEY1 = "CHANGE THIS"
+    KEY2 = "CHANGE THIS"
+  })
+
+  lifecycle {
+    ignore_changes = [secret_string, version_stages]
+  }
+}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 663 - 0
packages/app/docker/codebuild/terraform.tfstate


+ 0 - 6
packages/app/docker/nocdn/.env.production.local

@@ -1,6 +0,0 @@
-
-##
-## Handled by Next.js with dotenv or dotenv-flow
-## https://nextjs.org/docs/basic-features/environment-variables
-##
-NO_CDN=true

+ 2 - 2
packages/app/public/static/locales/en_US/admin.json

@@ -526,7 +526,7 @@
       "upload": "Upload",
       "upload": "Upload",
       "discard": "Discard uploaded data",
       "discard": "Discard uploaded data",
       "errors": {
       "errors": {
-        "different_versions": "This growi and the uploaded data versions are not met",
+        "different_versions": "The version of this GROWI and the uploaded data are not the same",
         "at_least_one": "Select one or more collections.",
         "at_least_one": "Select one or more collections.",
         "page_and_revision": "'Pages' and 'Revisions' must be imported both.",
         "page_and_revision": "'Pages' and 'Revisions' must be imported both.",
         "depends": "'{{target}}' must be selected when '{{condition}}' is selected."
         "depends": "'{{target}}' must be selected when '{{condition}}' is selected."
@@ -1033,7 +1033,7 @@
   "g2g": {
   "g2g": {
     "transfer_success": "Completed GROWI to GROWI transfer successfully",
     "transfer_success": "Completed GROWI to GROWI transfer successfully",
     "error_generate_growi_archive": "Failed to generate GROWI archive file",
     "error_generate_growi_archive": "Failed to generate GROWI archive file",
-    "error_send_growi_archive": "Failed to send GROWI archive file to new GROWI"
+    "error_send_growi_archive": "Failed to send GROWI archive file to the destination GROWI"
   },
   },
   "toaster": {
   "toaster": {
     "give_user_admin": "Succeeded to give {{username}} admin",
     "give_user_admin": "Succeeded to give {{username}} admin",

+ 1 - 1
packages/app/public/static/locales/en_US/commons.json

@@ -100,7 +100,7 @@
 
 
   "g2g_data_transfer": {
   "g2g_data_transfer": {
     "tab": "Data transfer",
     "tab": "Data transfer",
-    "data_transfer": "Growi To Growi Data Transfer",
+    "data_transfer": "GROWI To GROWI Data Transfer",
     "transfer_data_to_this_growi": "Transfer data from another GROWI to this GROWI",
     "transfer_data_to_this_growi": "Transfer data from another GROWI to this GROWI",
     "publish_transfer_key": "Publish transfer key",
     "publish_transfer_key": "Publish transfer key",
     "transfer_key_limit": "Transfer keys are valid for 1 hour after issuance.",
     "transfer_key_limit": "Transfer keys are valid for 1 hour after issuance.",

+ 2 - 2
packages/app/public/static/locales/zh_CN/admin.json

@@ -534,7 +534,7 @@
       "upload": "Upload",
       "upload": "Upload",
       "discard": "Discard uploaded data",
       "discard": "Discard uploaded data",
       "errors": {
       "errors": {
-        "versions_not_met": "this growi and the uploaded data versions are not met",
+        "different_versions": "The version of this GROWI and the uploaded data are not the same",
         "at_least_one": "Select one or more collections.",
         "at_least_one": "Select one or more collections.",
         "page_and_revision": "'Pages' and 'Revisions' must be imported both.",
         "page_and_revision": "'Pages' and 'Revisions' must be imported both.",
         "depends": "'{{target}}' must be selected when '{{condition}}' is selected."
         "depends": "'{{target}}' must be selected when '{{condition}}' is selected."
@@ -1041,7 +1041,7 @@
   "g2g": {
   "g2g": {
     "transfer_success": "Completed GROWI to GROWI transfer successfully",
     "transfer_success": "Completed GROWI to GROWI transfer successfully",
     "error_generate_growi_archive": "Failed to generate GROWI archive file",
     "error_generate_growi_archive": "Failed to generate GROWI archive file",
-    "error_send_growi_archive": "Failed to send GROWI archive file to new GROWI"
+    "error_send_growi_archive": "Failed to send GROWI archive file to the destination GROWI"
   },
   },
   "toaster": {
   "toaster": {
     "give_user_admin": "Succeeded to give {{username}} admin",
     "give_user_admin": "Succeeded to give {{username}} admin",

+ 6 - 0
packages/app/src/components/Admin/G2GDataTransferStatusIcon.tsx

@@ -31,6 +31,12 @@ const G2GDataTransferStatusIcon = ({ status, className, ...props }: Props): JSX.
     );
     );
   }
   }
 
 
+  if (status === G2G_PROGRESS_STATUS.SKIPPED) {
+    return (
+      <i className={`fa fa-ban fa-fw ${className}`} aria-label="skipped" {...props} />
+    );
+  }
+
   return <i className={`fa fa-circle-o fa-fw ${className}`} aria-label="pending" {...props} />;
   return <i className={`fa fa-circle-o fa-fw ${className}`} aria-label="pending" {...props} />;
 };
 };
 
 

+ 1 - 0
packages/app/src/interfaces/g2g-transfer.ts

@@ -6,6 +6,7 @@ export const G2G_PROGRESS_STATUS = {
   IN_PROGRESS: 'IN_PROGRESS',
   IN_PROGRESS: 'IN_PROGRESS',
   COMPLETED: 'COMPLETED',
   COMPLETED: 'COMPLETED',
   ERROR: 'ERROR',
   ERROR: 'ERROR',
+  SKIPPED: 'SKIPPED',
 } as const;
 } as const;
 
 
 /**
 /**

+ 0 - 1
packages/app/src/server/models/config.ts

@@ -230,7 +230,6 @@ schema.statics.getLocalconfig = function(crowi) {
       DRAWIO_URI: env.DRAWIO_URI || null,
       DRAWIO_URI: env.DRAWIO_URI || null,
       HACKMD_URI: env.HACKMD_URI || null,
       HACKMD_URI: env.HACKMD_URI || null,
       MATHJAX: env.MATHJAX || null,
       MATHJAX: env.MATHJAX || null,
-      NO_CDN: env.NO_CDN || null,
       GROWI_CLOUD_URI: env.GROWI_CLOUD_URI || null,
       GROWI_CLOUD_URI: env.GROWI_CLOUD_URI || null,
       GROWI_APP_ID_FOR_GROWI_CLOUD: env.GROWI_APP_ID_FOR_GROWI_CLOUD || null,
       GROWI_APP_ID_FOR_GROWI_CLOUD: env.GROWI_APP_ID_FOR_GROWI_CLOUD || null,
     },
     },

+ 8 - 8
packages/app/src/server/routes/apiv3/g2g-transfer.ts

@@ -184,7 +184,7 @@ module.exports = (crowi: Crowi): Router => {
       logger.error(err);
       logger.error(err);
       return res.apiv3Err(
       return res.apiv3Err(
         new ErrorV3(
         new ErrorV3(
-          'the version of this growi and the growi that exported the data are not met',
+          'The version of this GROWI and the uploaded GROWI data are not the same',
           'version_incompatible',
           'version_incompatible',
         ),
         ),
         500,
         500,
@@ -200,7 +200,7 @@ module.exports = (crowi: Crowi): Router => {
     }
     }
     catch (err) {
     catch (err) {
       logger.error(err);
       logger.error(err);
-      return res.apiv3Err(new ErrorV3('Import settings invalid. See growi docs about details.', 'import_settings_invalid'));
+      return res.apiv3Err(new ErrorV3('Import settings are invalid. See GROWI docs about details.', 'import_settings_invalid'));
     }
     }
 
 
     try {
     try {
@@ -252,7 +252,7 @@ module.exports = (crowi: Crowi): Router => {
       logger.error(err);
       logger.error(err);
 
 
       if (!isG2GTransferError(err)) {
       if (!isG2GTransferError(err)) {
-        return res.apiv3Err(new ErrorV3('Failed to prepare growi info', 'failed_to_prepare_growi_info'), 500);
+        return res.apiv3Err(new ErrorV3('Failed to prepare GROWI info', 'failed_to_prepare_growi_info'), 500);
       }
       }
 
 
       return res.apiv3Err(new ErrorV3(err.message, err.code), 500);
       return res.apiv3Err(new ErrorV3(err.message, err.code), 500);
@@ -302,17 +302,17 @@ module.exports = (crowi: Crowi): Router => {
     }
     }
 
 
     // get growi info
     // get growi info
-    let toGROWIInfo: IDataGROWIInfo;
+    let destGROWIInfo: IDataGROWIInfo;
     try {
     try {
-      toGROWIInfo = await g2gTransferPusherService.askGROWIInfo(tk);
+      destGROWIInfo = await g2gTransferPusherService.askGROWIInfo(tk);
     }
     }
     catch (err) {
     catch (err) {
       logger.error(err);
       logger.error(err);
-      return res.apiv3Err(new ErrorV3('Error occurred while asking GROWI growi info.', 'failed_to_ask_growi_info'));
+      return res.apiv3Err(new ErrorV3('Error occurred while asking GROWI info.', 'failed_to_ask_growi_info'));
     }
     }
 
 
     // Check if can transfer
     // Check if can transfer
-    const transferability = await g2gTransferPusherService.getTransferability(toGROWIInfo);
+    const transferability = await g2gTransferPusherService.getTransferability(destGROWIInfo);
     if (!transferability.canTransfer) {
     if (!transferability.canTransfer) {
       return res.apiv3Err(new ErrorV3(transferability.reason, 'growi_incompatible_to_transfer'));
       return res.apiv3Err(new ErrorV3(transferability.reason, 'growi_incompatible_to_transfer'));
     }
     }
@@ -320,7 +320,7 @@ module.exports = (crowi: Crowi): Router => {
     // Start transfer
     // Start transfer
     // DO NOT "await". Let it run in the background.
     // DO NOT "await". Let it run in the background.
     // Errors should be emitted through websocket.
     // Errors should be emitted through websocket.
-    g2gTransferPusherService.startTransfer(tk, req.user, collections, optionsMap);
+    g2gTransferPusherService.startTransfer(tk, req.user, collections, optionsMap, destGROWIInfo);
 
 
     return res.apiv3({ message: 'Successfully requested auto transfer.' });
     return res.apiv3({ message: 'Successfully requested auto transfer.' });
   });
   });

+ 3 - 3
packages/app/src/server/routes/apiv3/import.js

@@ -356,9 +356,9 @@ export default function route(crowi) {
       return res.apiv3(data);
       return res.apiv3(data);
     }
     }
     catch {
     catch {
-      const msg = 'the version of this growi and the growi that exported the data are not met';
-      const varidationErr = 'versions-are-not-met';
-      return res.apiv3Err(new ErrorV3(msg, varidationErr), 500);
+      const msg = 'The version of this GROWI and the uploaded GROWI data are not the same';
+      const validationErr = 'versions-are-not-met';
+      return res.apiv3Err(new ErrorV3(msg, validationErr), 500);
     }
     }
   });
   });
 
 

+ 0 - 6
packages/app/src/server/service/config-loader.ts

@@ -73,12 +73,6 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type:    ValueType.STRING,
     type:    ValueType.STRING,
     default: null,
     default: null,
   },
   },
-  NO_CDN: {
-    ns:      'crowi',
-    key:     'app:noCdn',
-    type:    ValueType.STRING,
-    default: null,
-  },
   // PLANTUML_URI: {
   // PLANTUML_URI: {
   //   ns:      ,
   //   ns:      ,
   //   key:     ,
   //   key:     ,

+ 1 - 1
packages/app/src/server/service/export.js

@@ -355,7 +355,7 @@ class ExportService {
 
 
     await streamToPromise(archive);
     await streamToPromise(archive);
 
 
-    logger.info(`zipped growi data into ${zipFile} (${archive.pointer()} bytes)`);
+    logger.info(`zipped GROWI data into ${zipFile} (${archive.pointer()} bytes)`);
 
 
     // delete json files
     // delete json files
     for (const { from } of configs) {
     for (const { from } of configs) {

+ 44 - 25
packages/app/src/server/service/g2g-transfer.ts

@@ -100,22 +100,22 @@ interface Pusher {
    */
    */
   generateAxiosConfig(tk: TransferKey, config: AxiosRequestConfig): AxiosRequestConfig
   generateAxiosConfig(tk: TransferKey, config: AxiosRequestConfig): AxiosRequestConfig
   /**
   /**
-   * Send to-growi a request to get growi info
+   * Send to-growi a request to get GROWI info
    * @param {TransferKey} tk Transfer key
    * @param {TransferKey} tk Transfer key
    */
    */
   askGROWIInfo(tk: TransferKey): Promise<IDataGROWIInfo>
   askGROWIInfo(tk: TransferKey): Promise<IDataGROWIInfo>
   /**
   /**
    * Check if transfering is proceedable
    * Check if transfering is proceedable
-   * @param {IDataGROWIInfo} fromGROWIInfo
+   * @param {IDataGROWIInfo} destGROWIInfo GROWI info from dest GROWI
    */
    */
-  getTransferability(fromGROWIInfo: IDataGROWIInfo): Promise<Transferability>
+  getTransferability(destGROWIInfo: IDataGROWIInfo): Promise<Transferability>
   /**
   /**
    * List files in the storage
    * List files in the storage
    * @param {TransferKey} tk Transfer key
    * @param {TransferKey} tk Transfer key
    */
    */
   listFilesInStorage(tk: TransferKey): Promise<FileMeta[]>
   listFilesInStorage(tk: TransferKey): Promise<FileMeta[]>
   /**
   /**
-   * Transfer all Attachment data to destination GROWI
+   * Transfer all Attachment data to dest GROWI
    * @param {TransferKey} tk Transfer key
    * @param {TransferKey} tk Transfer key
    */
    */
   transferAttachments(tk: TransferKey): Promise<void>
   transferAttachments(tk: TransferKey): Promise<void>
@@ -123,7 +123,7 @@ interface Pusher {
    * Start transfer data between GROWIs
    * Start transfer data between GROWIs
    * @param {TransferKey} tk TransferKey object
    * @param {TransferKey} tk TransferKey object
    * @param {any} user User operating g2g transfer
    * @param {any} user User operating g2g transfer
-   * @param {IDataGROWIInfo} toGROWIInfo GROWI info of new GROWI
+   * @param {IDataGROWIInfo} destGROWIInfo GROWI info of dest GROWI
    * @param {string[]} collections Collection name string array
    * @param {string[]} collections Collection name string array
    * @param {any} optionsMap Options map
    * @param {any} optionsMap Options map
    */
    */
@@ -132,6 +132,7 @@ interface Pusher {
     user: any,
     user: any,
     collections: string[],
     collections: string[],
     optionsMap: any,
     optionsMap: any,
+    destGROWIInfo: IDataGROWIInfo,
   ): Promise<void>
   ): Promise<void>
 }
 }
 
 
@@ -231,54 +232,64 @@ export class G2GTransferPusherService implements Pusher {
     }
     }
     catch (err) {
     catch (err) {
       logger.error(err);
       logger.error(err);
-      throw new G2GTransferError('Failed to retrieve growi info.', G2GTransferErrorCode.FAILED_TO_RETRIEVE_GROWI_INFO);
+      throw new G2GTransferError('Failed to retrieve GROWI info.', G2GTransferErrorCode.FAILED_TO_RETRIEVE_GROWI_INFO);
     }
     }
   }
   }
 
 
-  public async getTransferability(toGROWIInfo: IDataGROWIInfo): Promise<Transferability> {
-    const { fileUploadService } = this.crowi;
+  public async getTransferability(destGROWIInfo: IDataGROWIInfo): Promise<Transferability> {
+    const { fileUploadService, configManager } = this.crowi;
 
 
     const version = this.crowi.version;
     const version = this.crowi.version;
-    if (version !== toGROWIInfo.version) {
+    if (version !== destGROWIInfo.version) {
       return {
       return {
         canTransfer: false,
         canTransfer: false,
         // TODO: i18n for reason
         // TODO: i18n for reason
-        reason: `Growi versions mismatch. This Growi: ${version} / new Growi: ${toGROWIInfo.version}.`,
+        reason: `GROWI versions mismatch. src GROWI: ${version} / dest GROWI: ${destGROWIInfo.version}.`,
       };
       };
     }
     }
 
 
     const activeUserCount = await this.crowi.model('User').countActiveUsers();
     const activeUserCount = await this.crowi.model('User').countActiveUsers();
-    if ((toGROWIInfo.userUpperLimit ?? Infinity) < activeUserCount) {
+    if ((destGROWIInfo.userUpperLimit ?? Infinity) < activeUserCount) {
       return {
       return {
         canTransfer: false,
         canTransfer: false,
         // TODO: i18n for reason
         // TODO: i18n for reason
-        reason: `The number of active users (${activeUserCount} users) exceeds the limit of new Growi (to up ${toGROWIInfo.userUpperLimit} users).`,
+        // eslint-disable-next-line max-len
+        reason: `The number of active users (${activeUserCount} users) exceeds the limit of the destination GROWI (up to ${destGROWIInfo.userUpperLimit} users).`,
       };
       };
     }
     }
 
 
-    if (toGROWIInfo.fileUploadDisabled) {
+    if (destGROWIInfo.fileUploadDisabled) {
       return {
       return {
         canTransfer: false,
         canTransfer: false,
         // TODO: i18n for reason
         // TODO: i18n for reason
-        reason: 'File upload is disabled in new Growi.',
+        reason: 'The file upload setting is disabled in the destination GROWI.',
       };
       };
     }
     }
 
 
-    if (!toGROWIInfo.attachmentInfo.writable) {
+    if (configManager.getConfig('crowi', 'app:fileUploadType') === 'none') {
       return {
       return {
         canTransfer: false,
         canTransfer: false,
         // TODO: i18n for reason
         // TODO: i18n for reason
-        reason: 'The storage of new Growi is not writable.',
+        reason: 'File upload is not configured for src GROWI.',
+      };
+    }
+
+    const shouldUseFileUploadTypeOfDestGROWI = destGROWIInfo.attachmentInfo.type !== 'none';
+    if (shouldUseFileUploadTypeOfDestGROWI && !destGROWIInfo.attachmentInfo.writable) {
+      return {
+        canTransfer: false,
+        // TODO: i18n for reason
+        reason: 'The storage of the destination GROWI is not writable.',
       };
       };
     }
     }
 
 
     const totalFileSize = await fileUploadService.getTotalFileSize();
     const totalFileSize = await fileUploadService.getTotalFileSize();
-    if ((toGROWIInfo.fileUploadTotalLimit ?? Infinity) < totalFileSize) {
+    if ((destGROWIInfo.fileUploadTotalLimit ?? Infinity) < totalFileSize) {
       return {
       return {
         canTransfer: false,
         canTransfer: false,
         // TODO: i18n for reason
         // TODO: i18n for reason
         // eslint-disable-next-line max-len
         // eslint-disable-next-line max-len
-        reason: `Total file size exceeds file upload limit of new Growi. Requires ${totalFileSize.toLocaleString()} bytes, but got ${(toGROWIInfo.fileUploadTotalLimit ?? Infinity).toLocaleString()} bytes.`,
+        reason: `The total file size of attachments exceeds the file upload limit of the destination GROWI. Requires ${totalFileSize.toLocaleString()} bytes, but got ${(destGROWIInfo.fileUploadTotalLimit as number).toLocaleString()} bytes.`,
       };
       };
     }
     }
 
 
@@ -301,7 +312,7 @@ export class G2GTransferPusherService implements Pusher {
     const { fileUploadService, socketIoService } = this.crowi;
     const { fileUploadService, socketIoService } = this.crowi;
     const socket = socketIoService.getAdminSocket();
     const socket = socketIoService.getAdminSocket();
     const Attachment = this.crowi.model('Attachment');
     const Attachment = this.crowi.model('Attachment');
-    const filesFromNewGrowi = await this.listFilesInStorage(tk);
+    const filesFromSrcGROWI = await this.listFilesInStorage(tk);
 
 
     /**
     /**
      * Given these documents,
      * Given these documents,
@@ -344,8 +355,8 @@ export class G2GTransferPusherService implements Pusher {
      * | c.png | 1024 |
      * | c.png | 1024 |
      * | d.png | 2048 |
      * | d.png | 2048 |
      */
      */
-    const filter = filesFromNewGrowi.length > 0 ? {
-      $and: filesFromNewGrowi.map(({ name, size }) => ({
+    const filter = filesFromSrcGROWI.length > 0 ? {
+      $and: filesFromSrcGROWI.map(({ name, size }) => ({
         $or: [
         $or: [
           { fileName: { $ne: basename(name) } },
           { fileName: { $ne: basename(name) } },
           { fileSize: { $ne: size } },
           { fileSize: { $ne: size } },
@@ -391,7 +402,7 @@ export class G2GTransferPusherService implements Pusher {
   }
   }
 
 
   // eslint-disable-next-line max-len
   // eslint-disable-next-line max-len
-  public async startTransfer(tk: TransferKey, user: any, collections: string[], optionsMap: any): Promise<void> {
+  public async startTransfer(tk: TransferKey, user: any, collections: string[], optionsMap: any, destGROWIInfo: IDataGROWIInfo): Promise<void> {
     const socket = this.crowi.socketIoService.getAdminSocket();
     const socket = this.crowi.socketIoService.getAdminSocket();
 
 
     socket.emit('admin:g2gProgress', {
     socket.emit('admin:g2gProgress', {
@@ -422,7 +433,7 @@ export class G2GTransferPusherService implements Pusher {
       throw err;
       throw err;
     }
     }
 
 
-    // Send a zip file to other growi via axios
+    // Send a zip file to other GROWI via axios
     try {
     try {
       // Use FormData to immitate browser's form data object
       // Use FormData to immitate browser's form data object
       const form = new FormData();
       const form = new FormData();
@@ -441,7 +452,7 @@ export class G2GTransferPusherService implements Pusher {
         mongo: G2G_PROGRESS_STATUS.ERROR,
         mongo: G2G_PROGRESS_STATUS.ERROR,
         attachments: G2G_PROGRESS_STATUS.PENDING,
         attachments: G2G_PROGRESS_STATUS.PENDING,
       });
       });
-      socket.emit('admin:g2gError', { message: 'Failed to send GROWI archive file to new GROWI', key: 'admin:g2g:error_send_growi_archive' });
+      socket.emit('admin:g2gError', { message: 'Failed to send GROWI archive file to the destination GROWI', key: 'admin:g2g:error_send_growi_archive' });
       throw err;
       throw err;
     }
     }
 
 
@@ -450,6 +461,14 @@ export class G2GTransferPusherService implements Pusher {
       attachments: G2G_PROGRESS_STATUS.IN_PROGRESS,
       attachments: G2G_PROGRESS_STATUS.IN_PROGRESS,
     });
     });
 
 
+    if (destGROWIInfo.attachmentInfo.type === 'none' && ['aws', 'gcs'].includes(this.crowi.configManager.getConfig('crowi', 'app:fileUploadType'))) {
+      socket.emit('admin:g2gProgress', {
+        mongo: G2G_PROGRESS_STATUS.COMPLETED,
+        attachments: G2G_PROGRESS_STATUS.SKIPPED,
+      });
+      return;
+    }
+
     try {
     try {
       await this.transferAttachments(tk);
       await this.transferAttachments(tk);
     }
     }
@@ -470,7 +489,7 @@ export class G2GTransferPusherService implements Pusher {
   }
   }
 
 
   /**
   /**
-   * Transfer attachment to destination GROWI
+   * Transfer attachment to dest GROWI
    * @param {TransferKey} tk Transfer key
    * @param {TransferKey} tk Transfer key
    * @param {any} attachment Attachment model instance
    * @param {any} attachment Attachment model instance
    * @param {Readable} fileStream Attachment data(loaded from storage)
    * @param {Readable} fileStream Attachment data(loaded from storage)

+ 2 - 2
packages/app/src/server/service/import.js

@@ -507,14 +507,14 @@ class ImportService {
   /**
   /**
    * validate using meta.json
    * validate using meta.json
    * to pass validation, all the criteria must be met
    * to pass validation, all the criteria must be met
-   *   - ${version of this growi} === ${version of growi that exported data}
+   *   - ${version of this GROWI} === ${version of GROWI that exported data}
    *
    *
    * @memberOf ImportService
    * @memberOf ImportService
    * @param {object} meta meta data from meta.json
    * @param {object} meta meta data from meta.json
    */
    */
   validate(meta) {
   validate(meta) {
     if (meta.version !== this.crowi.version) {
     if (meta.version !== this.crowi.version) {
-      throw new Error('the version of this growi and the growi that exported the data are not met');
+      throw new Error('The version of this GROWI and the uploaded GROWI data are not the same');
     }
     }
 
 
     // TODO: check if all migrations are completed
     // TODO: check if all migrations are completed

+ 2 - 2
packages/app/src/server/util/createGrowiPagesFromImports.js

@@ -36,10 +36,10 @@ module.exports = (crowi) => {
       }
       }
       else {
       else {
         if (!isCreatableName) {
         if (!isCreatableName) {
-          errors.push(new Error(`${path} is not a creatable name in Growi`));
+          errors.push(new Error(`${path} is not a creatable name in GROWI`));
         }
         }
         if (isPageNameTaken) {
         if (isPageNameTaken) {
-          errors.push(new Error(`${path} already exists in Growi`));
+          errors.push(new Error(`${path} already exists in GROWI`));
         }
         }
       }
       }
     }
     }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor