Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.vscode
.idea
/.task/

# environment vars
.env
33 changes: 3 additions & 30 deletions docker/openemr/flex/openemr.sh
Original file line number Diff line number Diff line change
Expand Up @@ -689,38 +689,11 @@ if [[ "${NEED_COMPOSER_BUILD}" = "true" ]] || [[ "${NEED_NPM_BUILD}" = "true" ]]
return 1
}

token_configured=false

# if there is a raw github composer token supplied, then try to use it
# if there is a github composer token supplied, then try to use it
if [[ -n ${GITHUB_COMPOSER_TOKEN} ]]; then
echo 'trying raw github composer token'
# shellcheck disable=SC2310
if try_github_token "${GITHUB_COMPOSER_TOKEN}" 'raw github composer token'; then
token_configured=true
fi
fi

# if there is no raw github composer token supplied or it was invalid, try a base64 encoded one (if it was supplied)
if [[ ${token_configured} != true && -n ${GITHUB_COMPOSER_TOKEN_ENCODED} ]]; then
echo 'trying encoded github composer token'
decoded_token=$(base64 -d <<< "${GITHUB_COMPOSER_TOKEN_ENCODED}")
echo 'trying github composer token'
# shellcheck disable=SC2310
if try_github_token "${decoded_token}" 'encoded github composer token'; then
token_configured=true
fi
fi

# if there is no raw github composer token and/or base64 encoded one supplied or they were invalid, then try a character code encoded one (if it was supplied)
if [[ ${token_configured} != true && -n ${GITHUB_COMPOSER_TOKEN_ENCODED_ALTERNATE} ]]; then
echo 'trying alternate encoded github composer token'
# Word splitting is intentional here to convert space-separated string to array
# shellcheck disable=SC2206
codes=(${GITHUB_COMPOSER_TOKEN_ENCODED_ALTERNATE})
decoded_token=$(printf '%b' "$(printf '\\%03o' "${codes[@]}")")
# shellcheck disable=SC2310
if try_github_token "${decoded_token}" 'alternate encoded github composer token'; then
token_configured=true
fi
try_github_token "${GITHUB_COMPOSER_TOKEN}" 'github composer token' || true
fi

# install php dependencies
Expand Down
95 changes: 93 additions & 2 deletions utilities/openemr-cmd/openemr-cmd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ set -euo pipefail
#################################################################################################

# Increment the version when modify script
VERSION="1.0.41"
VERSION="1.0.42"

# ============================================================================
# WORKTREE STATE MANAGEMENT
Expand Down Expand Up @@ -1492,6 +1492,89 @@ docker-pull-image(){
done <<< "${services}"
}

# Walk the developer through creating/updating the .env file for the easydev
# docker-compose environment, so that secrets like GITHUB_COMPOSER_TOKEN are
# never committed to the repository in plaintext.
setup_composer_env() {
local ENV_FILE

if [[ ! -f "docker-compose.yml" ]]; then
echo "Error: docker-compose.yml not found in current directory." >&2
echo "Please run this command from any docker/development-* directory." >&2
exit 1
fi

ENV_FILE="../../.env"

echo ""
echo "=== OpenEMR Easydev Composer Token Setup ==="
echo ""
echo "A GitHub Personal Access Token lets Composer avoid GitHub API rate limits"
echo "when pulling dependencies. It should never be committed to the repository."
echo "This writes the GITHUB_COMPOSER_TOKEN to: ${ENV_FILE}"
echo ""

# Show current state if .env already exists
if [[ -f "${ENV_FILE}" ]]; then
local existing_token
existing_token=$(grep "^GITHUB_COMPOSER_TOKEN=" "${ENV_FILE}" | cut -d= -f2 || true)
if [[ -n "${existing_token}" ]]; then
echo "Current token in .env: ${existing_token:0:12}... (truncated for display)"
else
echo "Found existing .env but no GITHUB_COMPOSER_TOKEN entry."
fi
local RESP
read -r -e -p "Update it? [y/N] " RESP </dev/tty
if [[ -z "${RESP}" || "${RESP,,}" != "y" ]]; then
echo "No changes made."
return
fi
echo ""
fi

echo "Generate a fine-grained personal access token at: https://github.com/settings/tokens"
echo "you only need the default, read-only access for public repos, selected."
echo ""

local TOKEN
read -r -s -p "Paste your GitHub Personal Access Token: " TOKEN </dev/tty

if [[ -z "${TOKEN}" ]]; then
echo "Error: No token provided. Aborting." >&2
exit 1
fi

if [[ "${TOKEN}" != ghp_* && "${TOKEN}" != github_pat_* ]]; then
echo ""
echo "Warning: Token does not look like a standard GitHub PAT"
echo " (expected ghp_... or github_pat_... prefix)."
local RESP
read -r -e -p "Continue anyway? [y/N] " RESP </dev/tty
if [[ -z "${RESP}" || "${RESP,,}" != "y" ]]; then
echo "Aborting."
exit 1
fi
fi

# Write token to .env (overwrite if already present)
{
grep -v "^GITHUB_COMPOSER_TOKEN=" "${ENV_FILE}" 2>/dev/null || true
} > "${ENV_FILE}.tmp"
cat >> "${ENV_FILE}.tmp" << EOF
# OpenEMR easydev environment variables
# DO NOT COMMIT THIS FILE — contains sensitive credentials
GITHUB_COMPOSER_TOKEN=${TOKEN}
EOF
mv "${ENV_FILE}.tmp" "${ENV_FILE}"

echo ""
echo "✓ Written to ${ENV_FILE}: GITHUB_COMPOSER_TOKEN = ${TOKEN:0:12}..."
echo " (.env is covered by the root .gitignore)"

Copilot AI Apr 2, 2026

Copy link

Choose a reason for hiding this comment

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

This message claims the root .gitignore covers .env, but the repo’s .gitignore currently does not ignore .env. Since this command creates/updates ../../.env with a PAT, this is a real risk of accidentally committing credentials. Either update the repo ignore rules / use a file that’s already ignored, or change the guidance and default path.

Suggested change
echo " (.env is covered by the root .gitignore)"
echo " WARNING: ${ENV_FILE} is not ignored by git by default. Add it to .gitignore to avoid committing credentials."

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added .env to the .gitignore here in this repo even though it applies when running in openemr

echo ""
echo "Run: openemr-cmd up"
echo ""
}

USAGE_EXIT_CODE=13
VERSION_EXIT_CODE=14
FINAL_EXIT_CODE=0
Expand Down Expand Up @@ -1664,6 +1747,7 @@ if [[ $# -eq 0 || "${FIRST_ARG}" = '--help' || "${FIRST_ARG}" = '-h' ]]; then
echo " el, enable-ldap Turn on support for LDAP - login credentials are admin:admin"
echo " dld, disable-ldap Turn off support for LDAP - standard login credentials"
echo " ec, encoding-collation Change the database character set and collation"
echo " sce, setup-composer-env Create/update .env with GITHUB_COMPOSER_TOKEN (keeps secrets out of git)"

exit "${USAGE_EXIT_CODE}"

Expand Down Expand Up @@ -1747,7 +1831,7 @@ MARIADB_CONTAINER_ID="${mariadb_id:-}" # Set to empty if not found
# Check if a target container ID was determined or provided before proceeding with commands that need it
# (Allow proceeding if the command doesn't require a container, like up, down, start, stop, --help, --version)
case "${FIRST_ARG}" in
up|down|start|stop|--help|-h|--version|-v)
up|down|start|stop|--help|-h|--version|-v|sce|setup-composer-env)
# These commands don't necessarily need a running container ID determined here
;;
*)
Expand All @@ -1767,6 +1851,10 @@ esac
# For the shift usage, it used to cover the insane env.
case "${FIRST_ARG}" in
up)
if [[ ! -f "../../.env" ]] || ! grep -q "^GITHUB_COMPOSER_TOKEN=." "../../.env" 2>/dev/null; then
echo "No GITHUB_COMPOSER_TOKEN found in ../../.env — running setup first."
setup_composer_env
fi
run_docker_compose up -d
;;
down)
Expand Down Expand Up @@ -1839,6 +1927,9 @@ case "${FIRST_ARG}" in
ms|maria-shell)
quick_open_a_maria_docker_shell
;;
sce|setup-composer-env)
setup_composer_env
;;
bt)
run_devtools_in_docker "${CONTAINER_ID}" build-themes
;;
Expand Down
Loading