diff --git a/README.md b/README.md index d629516..44334f9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ RepoFoundry (`src/create-project.sh`) sets up a new project in one run: - a **Gitea** repository (the source of truth), - optionally an empty **GitHub** repository that receives everything through a **push mirror from Gitea to GitHub**, -- and a **local project** with credential-free remotes and the +- and a **local project** with one credential-free remote, `origin` (Gitea), and the [SQA-QC-Framework](https://git.tirsystem.com/TirSystem/SQA-QC-Framework) added as a git submodule, with its skills, git hooks (and optionally the plan gate) and templates installed. @@ -266,9 +266,9 @@ Without `--apply` that is all that happens. With `--apply` the script asks 1. the GitHub repository (empty), if chosen; 2. the Gitea repository (with the license that applies: `PROJECT_LICENSE`, or AGPL-3.0 for a public project with GitHub); 3. the push mirror Gitea -> GitHub, and a request for its first sync; -4. the local directory, `git init` on `main`, the `origin` remote (and `github` - if chosen), and, if the Gitea repository holds the license commit, that - history; +4. the local directory, `git init` on `main`, the `origin` remote (the only + remote: a push to it reaches GitHub through the mirror) and, if the Gitea + repository holds the license commit, that history; 5. the framework as the submodule `framework`; 6. the framework's skills and git hooks, and the plan gate if chosen; 7. `AGENTS.md` and `docs/artifact-registry.md` from the framework's templates. @@ -379,8 +379,10 @@ script stops before it creates anything when a preflight check is refused. - **No destructive commands.** The script never deletes a repository or a file and never uses a recursive delete; temporary files are removed one by one. -- **Credential-free remotes.** `origin` is `ssh://git@host:port/owner/name.git` - (or plain HTTPS when SSH is not used) and `github` is a plain HTTPS address. +- **Credential-free remote.** `origin` is `ssh://git@host:port/owner/name.git` + (or plain HTTPS when SSH is not used). There is no `github` remote: push to + `origin` and the mirror carries it to GitHub. A `github` remote made by an + earlier version is left alone; remove it with `git remote remove github`. - **Redirects are not followed,** so a token is only ever sent to the host in the URL it was meant for. Unknown SSH host keys are refused. - **Framework scripts run on the new project only.** They are run with diff --git a/src/lib/hosts.sh b/src/lib/hosts.sh index 7fcae2d..6ccc177 100644 --- a/src/lib/hosts.sh +++ b/src/lib/hosts.sh @@ -4,7 +4,7 @@ # # Part of create-project.sh: sourced by it, never run on its own. # -# Provides: is_reused, repo_owner, repo_url, gitea_host, origin_protocol, origin_url, github_remote_url, framework_url +# Provides: is_reused, repo_owner, repo_url, gitea_host, origin_protocol, origin_url, framework_url # is_reused HOST: succeed if the existing repository on HOST will be reused. is_reused() { @@ -54,10 +54,6 @@ origin_url() { fi } -github_remote_url() { - printf '%s/%s/%s.git' "${CONFIG[GITHUB_WEB_URL]}" "${PROJECT[github_owner]}" "${PROJECT[name]}" -} - # framework_url: where the framework submodule comes from (always SSH). framework_url() { printf 'ssh://git@%s:%s/%s.git' "$(gitea_host)" "${CONFIG[GITEA_SSH_PORT]}" \ diff --git a/src/lib/localproject.sh b/src/lib/localproject.sh index cb51dc6..96cd267 100644 --- a/src/lib/localproject.sh +++ b/src/lib/localproject.sh @@ -71,8 +71,10 @@ checkout_gitea_history() { fi } -# create_local_project: the directory, the git repository on main, the -# remotes and, when a license applies, the license history. No commit is made. +# create_local_project: the directory, the git repository on main, the origin +# remote and, when a license applies, the license history. No commit is made. +# Gitea is the only remote: a push to it reaches GitHub through the push +# mirror, so no github remote is added (and none that exists is removed). create_local_project() { local label="Local project" dir="${PROJECT[directory]}" begin_step "$label" @@ -82,9 +84,6 @@ create_local_project() { git_project "$dir" symbolic-ref HEAD "refs/heads/$DEFAULT_BRANCH" fi ensure_remote "$dir" origin "$(origin_url)" - if ((PROJECT[has_github])); then - ensure_remote "$dir" github "$(github_remote_url)" - fi if [[ -n ${PROJECT[license]} ]]; then checkout_gitea_history "$dir" fi diff --git a/tests/test-local.sh b/tests/test-local.sh index 8fe1f5d..48e77d4 100644 --- a/tests/test-local.sh +++ b/tests/test-local.sh @@ -35,7 +35,7 @@ readonly SSH_FRAMEWORK_URL="ssh://git@git.example.test:10022/TirSystem/SQA-QC-Fr # ----------------------------------------------------- directory and remotes -test_local_project_gets_credential_free_remotes_and_the_license_history() { +test_local_project_gets_the_origin_remote_only_and_the_license_history() { setup_hosts local dir="$WORK/project" local_answers "$dir" y n @@ -44,7 +44,9 @@ test_local_project_gets_credential_free_remotes_and_the_license_history() { assert_file_exists "directory created" "$dir/.git" assert_eq "branch is main" "main" "$(project_git "$dir" symbolic-ref --short HEAD)" assert_eq "origin over SSH, no credential" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" - assert_eq "github remote over HTTPS, no credential" "https://github.com/acme-org/my-app.git" "$(project_git "$dir" config --get remote.github.url)" + assert_eq "origin is the only remote, also with GitHub" "origin" "$(project_git "$dir" remote)" + assert_eq "no github remote" "" "$(project_git "$dir" config --get remote.github.url || true)" + assert_not_contains "no GitHub address in the git config" "$(cat "$dir/.git/config")" "github.com" assert_eq "the license commit is the whole history" "1" "$(project_git "$dir" rev-list --count HEAD)" assert_eq "it is the Gitea commit" "Initial commit" "$(project_git "$dir" log -1 --format=%s)" assert_file_exists "LICENSE from Gitea" "$dir/LICENSE" @@ -53,7 +55,7 @@ test_local_project_gets_credential_free_remotes_and_the_license_history() { assert_contains "reported" "$OUT" "Local project : created $dir (origin over SSH)" } -test_gitea_only_project_has_no_github_remote_and_no_commit() { +test_gitea_only_project_has_the_origin_remote_only_and_no_commit() { setup_hosts printf 'GITEA_TOKEN=%s\n' "$FAKE_GITEA_TOKEN" >"$WORK/.env" local dir="$WORK/project" @@ -61,7 +63,7 @@ test_gitea_only_project_has_no_github_remote_and_no_commit() { run_apply "$LOCAL_ANSWERS"$'y\n' assert_status "apply" 0 "$STATUS" assert_eq "origin" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" - assert_eq "no github remote" "" "$(project_git "$dir" config --get remote.github.url || true)" + assert_eq "origin is the only remote" "origin" "$(project_git "$dir" remote)" assert_file_missing "no license file" "$dir/LICENSE" assert_eq "no commit was made" "0" "$(project_git "$dir" rev-list --all --count)" assert_eq "no token in any file" "" "$(files_with_secret "$dir")" @@ -109,6 +111,20 @@ test_a_file_that_would_be_overwritten_by_the_license_history_is_kept() { assert_contains "later steps not attempted" "$OUT" "Framework : not attempted" } +test_a_github_remote_from_an_earlier_version_is_left_alone() { + setup_hosts + local dir="$WORK/project" + mkdir -p "$dir" + project_git "$dir" init -q + project_git "$dir" remote add github https://github.com/acme-org/my-app.git + local_answers "$dir" y n + run_apply "$LOCAL_ANSWERS"$'y\ny\n' + assert_status "apply" 0 "$STATUS" + assert_eq "the github remote is kept as it was" "https://github.com/acme-org/my-app.git" "$(project_git "$dir" config --get remote.github.url)" + assert_eq "origin was added beside it" "ssh://git@git.example.test:10022/TirSystem/my-app.git" "$(project_git "$dir" config --get remote.origin.url)" + assert_eq "no other remote" $'github\norigin' "$(project_git "$dir" remote | sort)" +} + test_a_remote_with_another_address_is_never_replaced() { setup_hosts local dir="$WORK/project" @@ -379,16 +395,15 @@ test_a_project_path_that_is_a_file_is_refused_in_the_preflight() { test_remote_addresses_are_built_from_the_configuration() { run_lib "" 'CONFIG[GITEA_URL]=https://git.example.test/sub -CONFIG[GITEA_SSH_PORT]=2222 CONFIG[FRAMEWORK_REPO]=Org/Fw CONFIG[GITHUB_WEB_URL]=https://github.com -PROJECT[gitea_owner]=TirSystem PROJECT[github_owner]=acme PROJECT[name]=my-app +CONFIG[GITEA_SSH_PORT]=2222 CONFIG[FRAMEWORK_REPO]=Org/Fw +PROJECT[gitea_owner]=TirSystem PROJECT[name]=my-app STATE[is_ssh_ok]=1 origin_url; echo STATE[is_ssh_ok]=0 origin_url; echo -github_remote_url; echo framework_url; echo gitea_host; echo' - assert_eq "addresses" $'ssh://git@git.example.test:2222/TirSystem/my-app.git\nhttps://git.example.test/sub/TirSystem/my-app.git\nhttps://github.com/acme/my-app.git\nssh://git@git.example.test:2222/Org/Fw.git\ngit.example.test' "$OUT" + assert_eq "addresses" $'ssh://git@git.example.test:2222/TirSystem/my-app.git\nhttps://git.example.test/sub/TirSystem/my-app.git\nssh://git@git.example.test:2222/Org/Fw.git\ngit.example.test' "$OUT" } test_the_https_fetch_hands_the_token_over_through_the_environment_only() {