diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..6c6bf0a --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +### Category +- [ ] New feature +- [ ] Bug fix +- [ ] Improvement +- [ ] Refactor +- [ ] etc + +### Description + +### Known issue \ No newline at end of file diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..06eb42d --- /dev/null +++ b/.github/workflows/README.md @@ -0,0 +1,53 @@ +## Naming rule +``` +[EVENT] CONTENT +``` + +## Versionning +- format +``` +{major}.{minor}.{patch}.{current_date} +``` +- scenario +``` +1.2.3 -> 1.2.3.xxxx -> 1.2.3.yyyy -> 1.2.4 +``` + + +## Workflows +> By default, [Push] includes a manual trigger (dispatch). + +- `[Push] Build dev` + - EVENT + - When code is pushed to master + - (triggered by `[Push] Sync CI`) + - When the workflow is manually triggered + - CONTENT + - Build code and push docker image to pyengine +- `[Dispatch] Release` + - EVENT + - When the workflow is manually triggered + - CONTENT + - Build code and push docker image to pyengine and spaceone +- `[Push] Sync CI` + - EVENT + - When code is pushed to master + - (trigger `[Push] Build dev`) + - When the workflow is manually triggered + - CONTENT + - [Push] + - Get workflows from actions and Trigger `[Push] Build dev` + - [Dispatch] + - Just get workflows from actions + +- `[PR] Review (TODO)` + +## Scenario +- Release: + - Manually trigger `[Dispatch] Release` +- Build Dev (Push): + - Commit code to master branch(`[Push] Sync CI` -> `[Push] Build dev`) +- Build Dev (Dispatch): + - Manually trigger `[Push] Build dev` +- Update workflows: + - Manually trigger `[Push] Sync CI` diff --git a/.github/workflows/check-pull-request.yml b/.github/workflows/check-pull-request.yml new file mode 100644 index 0000000..401dc0a --- /dev/null +++ b/.github/workflows/check-pull-request.yml @@ -0,0 +1,24 @@ +# .github/workflows/check-pull-request.yml +name: Check Pull Request + +on: + pull_request_target: + +jobs: + check-pull-request: + name: Check Pull Request + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Check signed commits + id: review + uses: cloudforet-io/check-pr-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Notify Result + if: ${{ steps.review.outputs.signedoff == 'false' }} + run: | + echo "The review result is ${{ steps.review.outputs.signedoff }}" + exit 1 diff --git a/.github/workflows/dispatch_build_dev.yaml b/.github/workflows/dispatch_build_dev.yaml new file mode 100644 index 0000000..7d83ed7 --- /dev/null +++ b/.github/workflows/dispatch_build_dev.yaml @@ -0,0 +1,163 @@ +name: "[Dispatch] Build Dev" + +on: + workflow_dispatch: + +env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + +jobs: + versioning: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.versioning.outputs.VERSION }} + steps: + - uses: actions/checkout@v2 + - name: get current date + run: | + sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime + echo "TIME=$(date +'%Y%m%d.%H%M%S')" >> $GITHUB_ENV + - name: set version with current date + id: versioning + run: | + echo "VERSION=$(sed 's/v//' < src/VERSION).${{ env.TIME }}" >> $GITHUB_OUTPUT + - name: Notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + docker: + if: github.repository_owner == 'cloudforet-io' + needs: versioning + runs-on: ubuntu-latest + env: + VERSION: ${{ needs.versioning.outputs.version }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: ${{ secrets.PAT_TOKEN }} + + - name: get service name + run: | + echo "SERVICE=$(echo ${{ github.repository }} | cut -d '/' -f2)" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push to pyengine + uses: docker/build-push-action@v4 + with: + context: . + push: true + tags: pyengine/${{ env.SERVICE }}:${{ env.VERSION }} + + - name: Notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + scan: + needs: [versioning, docker] + runs-on: ubuntu-20.04 + env: + VERSION: ${{ needs.versioning.outputs.version }} + steps: + - name: Run Trivy vulnerability scanner + id: trivy-scan + uses: aquasecurity/trivy-action@master + with: + image-ref: pyengine/${{ github.event.repository.name }}:${{ env.VERSION }} + format: 'sarif' + output: 'trivy-results.sarif' + ignore-unfixed: true + vuln-type: 'os,library' + severity: 'CRITICAL,HIGH' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: 'trivy-results.sarif' + + - name: Count vulnerabilities + id: vulnerabilities + run: | + count=$(jq '.runs[].results[].ruleId' ./trivy-results.sarif | wc -c) + echo "result_count=$count" >> $GITHUB_OUTPUT + echo "$count" + + - name: slack + if: ${{ steps.vulnerabilities.outputs.result_count != 0 }} + uses: 8398a7/action-slack@v3 + with: + status: custom + fields: workflowRun + custom_payload: | + { + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": ":warning: Image vulnerability detected" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Image:*\npyengine/${{ github.event.repository.name }}:${{ env.VERSION }}" + }, + { + "type": "mrkdwn", + "text": "*Repo name:*\n${{ github.repository }}" + } + ] + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": { + "type": "plain_text", + "emoji": true, + "text": "View Detail" + }, + "style": "danger", + "url": "https://github.com/${{ github.repository }}/security/code-scanning" + } + ] + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{secrets.VULNERABILITY_SLACK_WEBHOOK_URL}} + + notification: + runs-on: ubuntu-latest + needs: docker + steps: + - name: Slack + if: always() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,message,commit,author,action,ref,workflow,job + author_name: Github Action Slack diff --git a/.github/workflows/dispatch_docker_push.yml b/.github/workflows/dispatch_docker_push.yml deleted file mode 100644 index 96b55ad..0000000 --- a/.github/workflows/dispatch_docker_push.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: "[Dispath] Docker push" - -on: - push: - branches: - - master - -env: - BRANCH_NAME: master - -jobs: - docker: - runs-on: ubuntu-latest - outputs: - TIME: ${{ steps.get_date.outputs.TIME }} - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: ${{ env.BRANCH_NAME }} - token: ${{ secrets.TOKEN }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to Docker Hub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Get Date - id: get_date - run: | - sudo ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime - CURRENT_TIME=$(date +'%Y%m%d.%H%M%S') - - echo "TIME=$CURRENT_TIME" >> $GITHUB_ENV - echo "TIME=$CURRENT_TIME" >> $GITHUB_OUTPUT - - - name: Build and push to dockerhub - uses: docker/build-push-action@v4 - with: - context: . - push: true - tags: | - tjfals333/${{ github.event.repository.name }}:${{ env.TIME }} - build-args: | - PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - BRANCH_NAME=${{ env.BRANCH_NAME }} - provenance: false \ No newline at end of file diff --git a/.github/workflows/dispatch_release.yaml b/.github/workflows/dispatch_release.yaml new file mode 100644 index 0000000..2486def --- /dev/null +++ b/.github/workflows/dispatch_release.yaml @@ -0,0 +1,166 @@ +name: "[Dispatch] Release" + +on: + workflow_dispatch: + inputs: + version: + description: 'enter version(x.y.z)' + required: true + default: '2.0.0' + container_arch: + type: choice + description: 'choose container architecture' + default: linux/amd64,linux/arm64 + options: + - "linux/amd64" + - "linux/amd64,linux/arm64" + + +env: + VERSION: ${{ github.event.inputs.version }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + ARCH: ${{ github.event.inputs.container_arch }} + +jobs: + owner_check: + if: github.repository_owner == 'cloudforet-io' + runs-on: ubuntu-latest + steps: + - run: echo ${{ github.repository_owner }} + condition_check: + if: github.repository_owner == 'cloudforet-io' + runs-on: ubuntu-latest + needs: owner_check + steps: + - name: check version format + run: | + if [[ !(${{ env.VERSION }} =~ ^[0-9]\.[0-9]?[0-9]\.[0-9]?[0-9]$) ]]; + then + echo "You entered an incorrect version format." + exit 1 + fi + - name: debugging + run: | + echo "major=$(echo ${{env.VERSION}} | cut -c 2- | cut -d'.' -f1)" + echo "minor=$(echo ${{env.VERSION}} | cut -c 2- | cut -d'.' -f2)" + echo "patch=$(echo ${{env.VERSION}} | cut -c 2- | cut -d'.' -f3)" + - name: notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + update_master_branch_version_file: + needs: condition_check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + token: ${{ secrets.PAT_TOKEN }} + - name: update version file # That is used where the master_push actions + run: | + echo ${{ env.VERSION }} > src/VERSION + git config user.name github-actions + git config user.email github-actions@github.com + git add . + git commit -m "[CI/CD] release version ${{ env.VERSION }}" + - name: push changes + uses: ad-m/github-push-action@master + with: + github_token: ${{ secrets.PAT_TOKEN }} + branch: master + - name: notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + tagging: + needs: update_master_branch_version_file + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + token: ${{ secrets.PAT_TOKEN }} + - name: git tagging + run: | + git tag ${{ env.VERSION }} + git push origin "${{ env.VERSION }}" + - name: notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + docker: + needs: tagging + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: ${{ secrets.PAT_TOKEN }} + + - name: get service name + run: | + echo "SERVICE=$(echo ${{ github.repository }} | cut -d '/' -f2)" >> $GITHUB_ENV + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push to pyengine + uses: docker/build-push-action@v4 + with: + context: . + platforms: ${{ env.ARCH }} + push: true + tags: pyengine/${{ env.SERVICE }}:${{ env.VERSION }} + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.CLOUDFORET_DEV_DOCKER_USERNAME }} + password: ${{ secrets.CLOUDFORET_DEV_DOCKER_PASSWORD }} + + - name: Build and push to cloudforet + uses: docker/build-push-action@v4 + with: + context: . + platforms: ${{ env.ARCH }} + push: true + tags: cloudforet/${{ env.SERVICE }}:${{ env.VERSION }} + + - name: Notice when job fails + if: failure() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,workflow,job + author_name: Github Action Slack + + notification: + needs: docker + runs-on: ubuntu-latest + steps: + - name: Slack + if: always() + uses: 8398a7/action-slack@v3.2.0 + with: + status: ${{job.status}} + fields: repo,message,commit,author,action,ref,workflow,job + author_name: Github Action Slack diff --git a/.github/workflows/dispatch_sync_ci.yaml b/.github/workflows/dispatch_sync_ci.yaml new file mode 100644 index 0000000..ea49576 --- /dev/null +++ b/.github/workflows/dispatch_sync_ci.yaml @@ -0,0 +1,26 @@ +name: "[Dispatch] Sync CI" + +on: + workflow_dispatch: + +env: + REPO: cloudforet-io/actions + WORKFLOW_NAME: dispatch_apply_workflows.yaml + +jobs: + owner_check: + if: github.repository_owner == 'cloudforet-io' + runs-on: ubuntu-latest + steps: + - run: echo ${{ github.repository_owner }} + pull_workflows: + runs-on: ubuntu-latest + needs: owner_check + steps: + - name: request workflows + uses: benc-uk/workflow-dispatch@v1 + with: + token: ${{ secrets.PAT_TOKEN }} + repo: ${{ env.REPO }} + workflow: ${{ env.WORKFLOW_NAME }} + inputs: '{"dest" : "${{ github.event.repository.name }}"}' diff --git a/.github/workflows/push_build_dev.yaml b/.github/workflows/push_build_dev.yaml new file mode 100644 index 0000000..334eaa0 --- /dev/null +++ b/.github/workflows/push_build_dev.yaml @@ -0,0 +1,13 @@ +name: "[Push] Build dev" + +on: + workflow_dispatch: + +jobs: + none: + run-on: ubuntu-latest + steps: + - name: none + run: echo "This is deprecated." + +# deprecated workflow