Skip to content

feat: Github Action 배포 워크 플로우 추가#186

Merged
Soundbar91 merged 3 commits intodevelopfrom
feat/add-github-action-deploy
Mar 20, 2026
Merged

feat: Github Action 배포 워크 플로우 추가#186
Soundbar91 merged 3 commits intodevelopfrom
feat/add-github-action-deploy

Conversation

@Soundbar91
Copy link
Copy Markdown
Contributor

@Soundbar91 Soundbar91 commented Mar 20, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automated deployment pipelines for production and staging environments with Slack status notifications.
  • Removed Features

    • Bus schedules and commuting route information no longer available.
    • Calendar events, academic notices, and course information updates discontinued.
    • Image optimization and resizing service removed.

@Soundbar91 Soundbar91 self-assigned this Mar 20, 2026
@Soundbar91 Soundbar91 changed the base branch from master to develop March 20, 2026 12:19
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 20, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 171f3382-e499-438f-a95f-eb80172958a3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds two GitHub Actions CI/CD deployment workflows (production and staging) while removing numerous legacy data-crawling modules (notices, holidays, galleries, calendars, lectures), an entire Koreatech bus timetable Go service, and image scaling infrastructure.

Changes

Cohort / File(s) Summary
CI/CD Workflows
.github/workflows/deploy-prod.yml, .github/workflows/deploy-stage.yml
Added manual and automatic deployment workflows that archive the repository, transfer via SCP, execute remote deployment scripts, and post Slack notifications with execution status.
Crawling Modules - Data Scraping
crawling/dcinside_gallery.py, crawling/koreatech_notice.py, crawling/get_holiday.py, crawling/koreatech_calendar.py
Removed web-scraping modules that fetched articles, notices, holidays, and calendar events from external sources and persisted them to MySQL databases.
Crawling Modules - Graduation/Academic Data
crawling/graduation_credit_calculator/culture_hrd_msc.py, crawling/graduation_credit_calculator/major_subject.py, crawling/koreatech_closed_lecture.py
Removed PDF parsing and database synchronization modules for graduation requirements, course catalogs, and closed lecture tracking.
Koreatech Bus Service
crawling/koreatech_bus/main.go, crawling/koreatech_bus/go.mod, crawling/koreatech_bus/cheonan_*.yaml, crawling/koreatech_bus/cheongju_*.yaml, crawling/koreatech_bus/daejeon_commuting.yaml, crawling/koreatech_bus/sejong_commuting.yaml, crawling/koreatech_bus/seoul_commuting.yaml, crawling/koreatech_bus/config.example.properties
Removed entire Go-based bus timetable service including MongoDB/MySQL persistence logic and all regional shuttle/commuting route YAML configurations.
Database & Utility Modules
crawling/mysql_connect.py, crawling/search_migration.py, crawling/slack_notice.py
Removed database connection utilities, search article migration logic, and Slack notification helpers.
Image Scaling Service
image_scaling/image_scaling.py, image_scaling/image_scaling.sh, image_scaling/s3.example.config, image_scaling/s3_config.example.py
Removed S3-based image resizing and conversion pipeline including shell orchestration and configuration templates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Workflows ascend where crawlers once dwelled,
Bus routes dissolve, old services quelled.
To production we ship, with Slack by our side,
Legacy modules take their last ride. 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title describes adding GitHub Actions deployment workflows, which aligns with the main changes (two new workflow files added), but the changeset includes extensive removal of crawling modules and configuration files unrelated to GitHub Actions deployment. The title should reflect that this PR removes substantial legacy crawling infrastructure and bus shuttle code alongside adding deployment workflows, or split into separate PRs for deployment automation and cleanup.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/add-github-action-deploy
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
.github/workflows/deploy-stage.yml (1)

26-28: Consider excluding the archive itself to prevent issues on re-runs.

If this workflow runs again in the same workspace (e.g., due to caching or self-hosted runners), the tar command could include a stale batch.tar.gz from a previous run.

Proposed fix
      - name: Create tar archive
        run: |
-          tar -cvzf batch.tar.gz --exclude='.github' .
+          tar -cvzf batch.tar.gz --exclude='.github' --exclude='batch.tar.gz' .
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-stage.yml around lines 26 - 28, The tar step named
"Create tar archive" currently archives the whole workspace and may include an
existing batch.tar.gz from previous runs; update the tar invocation used in that
step to exclude the archive itself (e.g., add an --exclude for batch.tar.gz or a
pattern like *.tar.gz) so the produced archive cannot contain a stale
batch.tar.gz from earlier workflow executions.
.github/workflows/deploy-prod.yml (3)

26-28: Same tar archive concern as staging workflow.

Consider excluding batch.tar.gz to prevent potential issues on re-runs.

Proposed fix
      - name: Create tar archive
        run: |
-          tar -cvzf batch.tar.gz --exclude='.github' .
+          tar -cvzf batch.tar.gz --exclude='.github' --exclude='batch.tar.gz' .
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 26 - 28, The tar step named
"Create tar archive" currently archives everything and can include an existing
batch.tar.gz on reruns; update the tar invocation used in the "Create tar
archive" step to exclude the output archive itself (batch.tar.gz) by adding an
exclude for 'batch.tar.gz' so the archive won't recursively include or overwrite
itself during subsequent runs.

3-8: Consider restricting branch selection in workflow_dispatch inputs.

The current if: github.ref == 'refs/heads/master' guard silently skips the job if triggered from a non-master branch. Users may accidentally trigger from the wrong branch and see a skipped job without explanation. You could add an explicit branch restriction or provide feedback.

Option: Add input with explicit restriction
 on:
   workflow_dispatch:
+    # Note: This workflow only runs on the master branch.
+    # If triggered from another branch, the deploy job will be skipped.

Alternatively, you could remove the if condition entirely since GitHub allows limiting workflow_dispatch to specific branches in repository settings, which provides a better UX.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 3 - 8, The job currently uses
a silent guard "if: github.ref == 'refs/heads/master'" which can lead to
confusing skipped runs when triggered via workflow_dispatch; add a
workflow_dispatch input (e.g., inputs.branch with a default of "master" and
allowed choices) and update the deploy job's condition to explicitly validate
the input when the event is a manual dispatch (use github.event_name ==
'workflow_dispatch' and github.event.inputs.branch == 'master') while preserving
the original ref check for non-dispatch runs, or alternatively remove the silent
if and rely on repository-level branch restrictions—modify the workflow_dispatch
block and the deploy job's if condition (referencing workflow_dispatch,
inputs.branch, deploy job, and the existing if github.ref check) to implement
one of these options so users get an explicit branch choice or clear behavior.

1-68: Consider extracting a reusable workflow to reduce duplication.

Both deploy-stage.yml and deploy-prod.yml share nearly identical logic. This duplication increases maintenance burden. You could create a reusable workflow (composite action or called workflow) that accepts environment-specific inputs/secrets.

Example structure for a reusable workflow:

# .github/workflows/deploy-reusable.yml
on:
  workflow_call:
    inputs:
      environment:
        required: true
        type: string
    secrets:
      SSH_HOST:
        required: true
      # ... other secrets

Then both workflows can call it with their respective environment parameters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 1 - 68, Extract the
duplicated "deploy" job steps (the tar creation, scp transfer, ssh deploy, and
Slack notifications currently in the deploy job and steps like "Notify Slack
deploy started", "Create tar archive", "Transfer archive via SCP", "Run deploy
script via SSH", "Notify Slack deploy result") into a reusable workflow that
uses on: workflow_call with inputs for environment, repo/branch/actor/run id (or
derive via github context) and required secrets
(PROD_SSH_HOST/PROD_SSH_USER/PROD_SSH_KEY/PROD_SSH_PORT/PROD_DEPLOY_PATH/PROD_DEPLOY_SCRIPT_PATH
and PROD_SLACK_DEPLOY_WEBHOOK_URL as generic names like SSH_HOST, SSH_USER,
SSH_KEY, SSH_PORT, DEPLOY_PATH, DEPLOY_SCRIPT_PATH, SLACK_WEBHOOK); then replace
deploy-prod.yml and deploy-stage.yml with minimal caller workflows that call the
new reusable workflow, passing environment-specific inputs and mapping the
appropriate secrets from each environment, and ensure the reusable workflow
preserves the start time/output behavior used by "Notify Slack deploy result".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy-prod.yml:
- Around line 49-62: The duration calculation in the "Notify Slack deploy
result" step assumes steps.start.outputs.time exists and will fail if the
"Record start time" step didn't produce it; update the run block to first
compute a START timestamp variable by checking whether steps.start.outputs.time
is non-empty and using it, otherwise fallback to the current epoch seconds, then
compute DURATION, MINUTES and SECONDS from that START value (references: the run
block variables DURATION, MINUTES, SECONDS and steps.start.outputs.time in the
"Notify Slack deploy result" step).

In @.github/workflows/deploy-stage.yml:
- Around line 49-62: The notification step can fail if steps.start.outputs.time
is empty; update the "Notify Slack deploy result" step (where DURATION and
START_TIME are computed) to defensively handle a missing start time by checking
if steps.start.outputs.time is empty and using a safe fallback (e.g., treat
missing start time as now or 0) before performing arithmetic, e.g., set a
START_TIME variable from steps.start.outputs.time and use shell parameter
expansion to default it (START_TIME=${START_TIME:-0}) or skip duration
calculation when empty, then compute DURATION/MINUTES/SECONDS only when
START_TIME is valid and continue to use job.status/EMOJI/STATUS as before.

---

Nitpick comments:
In @.github/workflows/deploy-prod.yml:
- Around line 26-28: The tar step named "Create tar archive" currently archives
everything and can include an existing batch.tar.gz on reruns; update the tar
invocation used in the "Create tar archive" step to exclude the output archive
itself (batch.tar.gz) by adding an exclude for 'batch.tar.gz' so the archive
won't recursively include or overwrite itself during subsequent runs.
- Around line 3-8: The job currently uses a silent guard "if: github.ref ==
'refs/heads/master'" which can lead to confusing skipped runs when triggered via
workflow_dispatch; add a workflow_dispatch input (e.g., inputs.branch with a
default of "master" and allowed choices) and update the deploy job's condition
to explicitly validate the input when the event is a manual dispatch (use
github.event_name == 'workflow_dispatch' and github.event.inputs.branch ==
'master') while preserving the original ref check for non-dispatch runs, or
alternatively remove the silent if and rely on repository-level branch
restrictions—modify the workflow_dispatch block and the deploy job's if
condition (referencing workflow_dispatch, inputs.branch, deploy job, and the
existing if github.ref check) to implement one of these options so users get an
explicit branch choice or clear behavior.
- Around line 1-68: Extract the duplicated "deploy" job steps (the tar creation,
scp transfer, ssh deploy, and Slack notifications currently in the deploy job
and steps like "Notify Slack deploy started", "Create tar archive", "Transfer
archive via SCP", "Run deploy script via SSH", "Notify Slack deploy result")
into a reusable workflow that uses on: workflow_call with inputs for
environment, repo/branch/actor/run id (or derive via github context) and
required secrets
(PROD_SSH_HOST/PROD_SSH_USER/PROD_SSH_KEY/PROD_SSH_PORT/PROD_DEPLOY_PATH/PROD_DEPLOY_SCRIPT_PATH
and PROD_SLACK_DEPLOY_WEBHOOK_URL as generic names like SSH_HOST, SSH_USER,
SSH_KEY, SSH_PORT, DEPLOY_PATH, DEPLOY_SCRIPT_PATH, SLACK_WEBHOOK); then replace
deploy-prod.yml and deploy-stage.yml with minimal caller workflows that call the
new reusable workflow, passing environment-specific inputs and mapping the
appropriate secrets from each environment, and ensure the reusable workflow
preserves the start time/output behavior used by "Notify Slack deploy result".

In @.github/workflows/deploy-stage.yml:
- Around line 26-28: The tar step named "Create tar archive" currently archives
the whole workspace and may include an existing batch.tar.gz from previous runs;
update the tar invocation used in that step to exclude the archive itself (e.g.,
add an --exclude for batch.tar.gz or a pattern like *.tar.gz) so the produced
archive cannot contain a stale batch.tar.gz from earlier workflow executions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a6192775-5f7b-4130-96e0-9f1a66a91bda

📥 Commits

Reviewing files that changed from the base of the PR and between 5bfe0ca and c305d84.

⛔ Files ignored due to path filters (7)
  • crawling/graduation_credit_calculator/pdfs/2019대학요람.pdf is excluded by !**/*.pdf
  • crawling/graduation_credit_calculator/pdfs/2020대학요람.pdf is excluded by !**/*.pdf
  • crawling/graduation_credit_calculator/pdfs/2021대학요람.pdf is excluded by !**/*.pdf
  • crawling/graduation_credit_calculator/pdfs/2022대학요람.pdf is excluded by !**/*.pdf
  • crawling/graduation_credit_calculator/pdfs/2023대학요람.pdf is excluded by !**/*.pdf
  • crawling/graduation_credit_calculator/pdfs/2024대학요람.pdf is excluded by !**/*.pdf
  • crawling/koreatech_bus/go.sum is excluded by !**/*.sum
📒 Files selected for processing (27)
  • .github/workflows/deploy-prod.yml
  • .github/workflows/deploy-stage.yml
  • crawling/dcinside_gallery.py
  • crawling/get_holiday.py
  • crawling/graduation_credit_calculator/culture_hrd_msc.py
  • crawling/graduation_credit_calculator/major_subject.py
  • crawling/koreatech_bus/cheonan_commuting.yaml
  • crawling/koreatech_bus/cheonan_shuttle.yaml
  • crawling/koreatech_bus/cheongju_commuting.yaml
  • crawling/koreatech_bus/cheongju_shuttle.yaml
  • crawling/koreatech_bus/config.example.properties
  • crawling/koreatech_bus/daejeon_commuting.yaml
  • crawling/koreatech_bus/go.mod
  • crawling/koreatech_bus/main.go
  • crawling/koreatech_bus/sejong_commuting.yaml
  • crawling/koreatech_bus/seoul_commuting.yaml
  • crawling/koreatech_calendar.py
  • crawling/koreatech_closed_lecture.py
  • crawling/koreatech_lecture/lecture.py
  • crawling/koreatech_notice.py
  • crawling/mysql_connect.py
  • crawling/search_migration.py
  • crawling/slack_notice.py
  • image_scaling/image_scaling.py
  • image_scaling/image_scaling.sh
  • image_scaling/s3.example.config
  • image_scaling/s3_config.example.py
💤 Files with no reviewable changes (24)
  • crawling/koreatech_bus/config.example.properties
  • crawling/koreatech_bus/daejeon_commuting.yaml
  • crawling/get_holiday.py
  • crawling/koreatech_bus/go.mod
  • crawling/koreatech_bus/cheongju_shuttle.yaml
  • crawling/koreatech_calendar.py
  • crawling/koreatech_bus/cheonan_commuting.yaml
  • crawling/slack_notice.py
  • image_scaling/image_scaling.sh
  • crawling/koreatech_bus/cheongju_commuting.yaml
  • crawling/koreatech_closed_lecture.py
  • crawling/mysql_connect.py
  • crawling/koreatech_bus/main.go
  • crawling/koreatech_bus/seoul_commuting.yaml
  • image_scaling/image_scaling.py
  • image_scaling/s3_config.example.py
  • crawling/graduation_credit_calculator/culture_hrd_msc.py
  • crawling/koreatech_bus/cheonan_shuttle.yaml
  • crawling/koreatech_bus/sejong_commuting.yaml
  • crawling/graduation_credit_calculator/major_subject.py
  • image_scaling/s3.example.config
  • crawling/search_migration.py
  • crawling/koreatech_notice.py
  • crawling/dcinside_gallery.py

Comment on lines +49 to +62
- name: Notify Slack deploy result
if: always()
run: |
DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))

if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Same start time fallback concern as staging workflow.

If the "Record start time" step fails, the duration calculation will error. Add a fallback for robustness.

Proposed fix
      - name: Notify Slack deploy result
        if: always()
        run: |
+          START_TIME="${{ steps.start.outputs.time }}"
+          if [ -z "$START_TIME" ]; then
+            START_TIME=$(date +%s)
+          fi
-          DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
+          DURATION=$(( $(date +%s) - START_TIME ))
          MINUTES=$((DURATION / 60))
          SECONDS=$((DURATION % 60))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Notify Slack deploy result
if: always()
run: |
DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
- name: Notify Slack deploy result
if: always()
run: |
START_TIME="${{ steps.start.outputs.time }}"
if [ -z "$START_TIME" ]; then
START_TIME=$(date +%s)
fi
DURATION=$(( $(date +%s) - START_TIME ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-prod.yml around lines 49 - 62, The duration
calculation in the "Notify Slack deploy result" step assumes
steps.start.outputs.time exists and will fail if the "Record start time" step
didn't produce it; update the run block to first compute a START timestamp
variable by checking whether steps.start.outputs.time is non-empty and using it,
otherwise fallback to the current epoch seconds, then compute DURATION, MINUTES
and SECONDS from that START value (references: the run block variables DURATION,
MINUTES, SECONDS and steps.start.outputs.time in the "Notify Slack deploy
result" step).

Comment on lines +49 to +62
- name: Notify Slack deploy result
if: always()
run: |
DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))

if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Result notification may fail silently if start time step didn't complete.

If the "Record start time" step fails or is skipped, steps.start.outputs.time will be empty, causing the arithmetic in line 52 to fail. Since this runs with if: always(), this edge case is possible.

Proposed fix to add a fallback
      - name: Notify Slack deploy result
        if: always()
        run: |
+          START_TIME="${{ steps.start.outputs.time }}"
+          if [ -z "$START_TIME" ]; then
+            START_TIME=$(date +%s)
+          fi
-          DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
+          DURATION=$(( $(date +%s) - START_TIME ))
          MINUTES=$((DURATION / 60))
          SECONDS=$((DURATION % 60))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Notify Slack deploy result
if: always()
run: |
DURATION=$(( $(date +%s) - ${{ steps.start.outputs.time }} ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
- name: Notify Slack deploy result
if: always()
run: |
START_TIME="${{ steps.start.outputs.time }}"
if [ -z "$START_TIME" ]; then
START_TIME=$(date +%s)
fi
DURATION=$(( $(date +%s) - START_TIME ))
MINUTES=$((DURATION / 60))
SECONDS=$((DURATION % 60))
if [ "${{ job.status }}" = "success" ]; then
EMOJI=":white_check_mark:"
STATUS="성공"
else
EMOJI=":x:"
STATUS="실패"
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-stage.yml around lines 49 - 62, The notification
step can fail if steps.start.outputs.time is empty; update the "Notify Slack
deploy result" step (where DURATION and START_TIME are computed) to defensively
handle a missing start time by checking if steps.start.outputs.time is empty and
using a safe fallback (e.g., treat missing start time as now or 0) before
performing arithmetic, e.g., set a START_TIME variable from
steps.start.outputs.time and use shell parameter expansion to default it
(START_TIME=${START_TIME:-0}) or skip duration calculation when empty, then
compute DURATION/MINUTES/SECONDS only when START_TIME is valid and continue to
use job.status/EMOJI/STATUS as before.

@Soundbar91 Soundbar91 merged commit 6a6fd3c into develop Mar 20, 2026
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Mar 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant