{"id":15064545,"url":"https://github.com/tom-barone/jqc","last_synced_at":"2026-01-02T22:39:27.530Z","repository":{"id":157903124,"uuid":"578141267","full_name":"tom-barone/JQC","owner":"tom-barone","description":"Work management system built with Rails","archived":false,"fork":false,"pushed_at":"2025-03-13T00:53:03.000Z","size":2937,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-13T01:22:46.536Z","etag":null,"topics":["bootstrap","github-actions","postgresql","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tom-barone.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-14T11:00:59.000Z","updated_at":"2025-03-13T00:47:00.000Z","dependencies_parsed_at":"2024-04-14T07:22:46.159Z","dependency_job_id":"a6a57f3e-dded-4f6e-8773-429c04f08db9","html_url":"https://github.com/tom-barone/JQC","commit_stats":null,"previous_names":["tom-barone/jqc"],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tom-barone%2FJQC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tom-barone%2FJQC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tom-barone%2FJQC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tom-barone%2FJQC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tom-barone","download_url":"https://codeload.github.com/tom-barone/JQC/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243790999,"owners_count":20348385,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bootstrap","github-actions","postgresql","rails","ruby"],"created_at":"2024-09-25T00:20:25.668Z","updated_at":"2026-01-02T22:39:27.524Z","avatar_url":"https://github.com/tom-barone.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JQC\n\n[![License](https://img.shields.io/github/license/tom-barone/JQC?color=969696)](https://github.com/tom-barone/JQC/blob/master/LICENSE)\n\n[![Continuous Integration](https://github.com/tom-barone/JQC/actions/workflows/continuous-integration.yml/badge.svg?branch=develop)](https://github.com/tom-barone/JQC/actions/workflows/continuous-integration.yml) [![Continuous Deployment](https://github.com/tom-barone/JQC/actions/workflows/continuous-deployment.yml/badge.svg?branch=master)](https://github.com/tom-barone/JQC/actions/workflows/continuous-deployment.yml) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=tom-barone_JQC\u0026metric=alert_status)](https://sonarcloud.io/summary/overall?id=tom-barone_JQC)\n\n[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=tom-barone_JQC\u0026metric=security_rating)](https://sonarcloud.io/summary/overall?id=tom-barone_JQC) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=tom-barone_JQC\u0026metric=reliability_rating)](https://sonarcloud.io/summary/overall?id=tom-barone_JQC) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=tom-barone_JQC\u0026metric=sqale_rating)](https://sonarcloud.io/summary/overall?id=tom-barone_JQC) [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=tom-barone_JQC\u0026metric=vulnerabilities)](https://sonarcloud.io/summary/overall?id=tom-barone_JQC)\n\nRails/PostgreSQL app deployed with Dokku and styled with Bootstrap.\n\n## Getting started\n\nAll work is done on the `develop` branch.\n\nAfter committing and pushing to `develop`, the [CI Github Action](https://github.com/tom-barone/JQC/actions/workflows/continuous-integration.yml) will:\n\n1. Run the unit, integration and end to end tests.\n1. Deploy a staging site.\n1. Run a set of smaller, production safe checks against the staging site.\n\nTo deploy a new production version:\n\n1. Do a manual smoke test of the staging site.\n1. Create a pull request to merge `develop` -\u003e `master`.\n1. Once all checks have passed, the pull request will automatically merge.\n1. The [CD Github Action](https://github.com/tom-barone/JQC/actions/workflows/continuous-deployment.yml) will deploy a new production version to dokku, run the production safe checks and create a new git release tag.\n\n## Monitoring\n\nIf deployed using [tom-barone/web-server-init](https://github.com/tom-barone/web-server-init), there is a [Grafana](https://grafana.com) / [Graphite](https://graphiteapp.org/) instance available at `http://monitoring.\u003cwebsite_domain\u003e` to use.\n\nDefinitions for a working Grafana dashboard and set of alerts are included in the `/monitoring` directory.\n\n![Grafana Dashboard Screenshot](./monitoring/grafana_dashboard_screenshot.png)\n\nAlerts:\n\n- Disk storage almost full.\n- JQC RAM usage too high.\n- System RAM usage too high.\n- CPU usage too high.\n\n## Deployment\n\n### Dokku\n\n```bash\n# Create the app\nssh -t \u003cuser\u003e@\u003cdokku_server\u003e dokku apps:create \u003cwebsite_domain\u003e\n# Add the dokku git remote to the repo\ngit remote add \u003cremote_name\u003e ssh://dokku@\u003cdokku_server\u003e:\u003cport\u003e/\u003cwebsite_domain\u003e\n# Set the domain for the dokku container\ndokku --remote \u003cremote_name\u003e domains:set \u003cwebsite_domain\u003e\n# Create \u0026 link postgres and redis containers (can limit memory usage in MB with --memory)\ndokku --remote \u003cremote_name\u003e postgres:create \u003capp_name\u003e-db --memory 1024\ndokku --remote \u003cremote_name\u003e postgres:link \u003capp_name\u003e-db \u003cwebsite_domain\u003e\ndokku --remote \u003cremote_name\u003e redis:create \u003capp_name\u003e-redis\ndokku --remote \u003cremote_name\u003e redis:link \u003capp_name\u003e-redis \u003cwebsite_domain\u003e\n# Set important environment variables\ndokku --remote \u003cremote_name\u003e config:set RAILS_MASTER_KEY=$(cat config/master.key)\ndokku --remote \u003cremote_name\u003e config:set DOMAIN=\u003cwebsite_domain\u003e\n# Set on the staging environment\ndokku --remote \u003cremote_name\u003e config:set STAGING=true\n# Setup LetsEncrypt certs\n# - Make sure to have your domain DNS settings point \u003cwebsite_domain\u003e to the server before running this\ndokku --remote \u003cremote_name\u003e letsencrypt:enable\n# If using a branch other than main or master to deploy from\ndokku --remote \u003cremote_name\u003e git:set deploy-branch \u003cbranch_name\u003e\n# Push the code to the server and deploy\ngit push \u003cremote_name\u003e \u003cbranch\u003e\n# Scale up the web and worker processes\ndokku --remote \u003cremote_name\u003e ps:scale web=1 worker=1\n# Limit the app resources, set these to whatever you need\n# See https://docs.docker.com/engine/containers/resource_constraints\ndokku --remote \u003cremote_name\u003e resource:limit --memory 1.5g --process-type web\ndokku --remote \u003cremote_name\u003e resource:limit --memory 500m --process-type worker\ndokku --remote \u003cremote_name\u003e resource:report\n# Setup persistent logging to a file at /var/log/dokku/apps/\u003capp_name\u003e.log\n# The regular app logs are not kept between container restarts / deploys\ndokku --remote \u003cremote_name\u003e logs:set vector-sink \"file://?encoding[codec]=csv\u0026encoding[csv][fields][]=timestamp\u0026encoding[csv][fields][]=message\u0026encoding[csv][quote_style]=always\u0026path=/var/log/dokku/apps/\u003capp_name\u003e.log\"\ndokku --remote \u003cremote_name\u003e logs:vector-start\n# If using dokku-graphite and reporting with StatsD,\n# this will make the environment variable STATSD_URL available in the app\ndokku --remote \u003cremote_name\u003e graphite:link \u003cgraphite_service\u003e \u003capp_name\u003e\n\n# Anytime you need to deploy a new release\ngit push \u003cremote_name\u003e \u003cbranch\u003e\n```\n\nYou can omit the `\u003cremote_name\u003e` and keep it as the default `dokku` remote if you like. But it's nice if you've got a staging and production servers to have different remotes, e.g. `staging` and `production`. That way you can deploy to each server with:\n\n```bash\ngit push staging master\ngit push production master\n```\n\nI like to use `pgAdmin` to interface with the postgres database, which can be done with SSH tunneling. First you'll need to expose the database port from the docker container to the host machine:\n\n```bash\n# Expose the database internally from dokku to 0.0.0.0 on the host\ndokku --remote \u003cremote_name\u003e postgres:expose \u003capp_name\u003e-db 5432\n# Undo the port expose with\ndokku --remote \u003cremote_name\u003e postgres:unexpose \u003capp_name\u003e-db 5432\n# View the connection string (password etc.) and use it in pgAdmin, along with relevant SSH tunnel settings\ndokku --remote \u003cremote_name\u003e postgres:info \u003capp_name\u003e-db\n```\n\nSometimes it's handy to blast away the database and start fresh:\n\n```bash\ndokku --remote \u003cremote_name\u003e postgres:unlink \u003capp_name\u003e-db \u003cwebsite_domain\u003e\ndokku --remote \u003cremote_name\u003e postgres:destroy \u003capp_name\u003e-db --force\ndokku --remote \u003cremote_name\u003e postgres:create \u003capp_name\u003e-db\ndokku --remote \u003cremote_name\u003e postgres:link \u003capp_name\u003e-db \u003cwebsite_domain\u003e\n```\n\nTo recreate the database from a backup\n\n```bash\n# Downloads the most recent backup to ./backup/export\nrake fetch_most_recent_backup\n# For a local development database\npg_restore --clean --dbname=\u003clocal_db_name\u003e --exit-on-error backup/export\n# For a dokku hosted database (you may need to blast away and recreate the database first)\ndokku --remote \u003cremote_name\u003e postgres:import \u003capp_name\u003e-db \u003c backup/export\n```\n\n## Development\n\nThere are a few issues with `solid_queue` causing trouble when resetting the database. To reset everything from scratch so we can load in backed up data in development:\n\n```bash\nrails db:migrate:reset\nrails db:drop:queue\n# Reset the db/queue_schema.rb file\nrails db:prepare\nrake restore_development_db_from_most_recent_backup\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftom-barone%2Fjqc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftom-barone%2Fjqc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftom-barone%2Fjqc/lists"}