diff --git a/.github/workflows/convert.sh b/.github/workflows/convert.sh
new file mode 100755
index 000000000..14145778c
--- /dev/null
+++ b/.github/workflows/convert.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+# convert.sh
+#
+# Perform the conversion from Chromium to ungoogled-chromium
+#
+
+set -e
+
+test -n "$DOWNLOAD_DIR"
+test -n "$OUTPUT_DIR"
+test -n "$STATE_DIR"
+test -n "$WORK_DIR"
+test -d "$GITHUB_WORKSPACE"
+
+uc_git=$GITHUB_WORKSPACE/ungoogled-chromium
+
+wrap=
+
+tab=' '
+
+run()
+{
+ echo "+ $*"
+ env "$@"
+ echo ' '
+}
+
+do_conversion()
+{
+ local codename="$1" deb_version="$2" uc_tag="$3"
+ local conv_dir=$WORK_DIR/convert/$codename
+
+ echo "Using ungoogled-chromium Git tag $uc_tag ..."
+ (cd $uc_git && run git switch --detach $uc_tag)
+
+ rm -rf $conv_dir
+ mkdir -p $conv_dir
+
+ echo 'Unpacking source package ...'
+ run dpkg-source \
+ --no-copy \
+ --require-valid-signature \
+ --skip-patches \
+ --extract \
+ $DOWNLOAD_DIR/chromium_$deb_version.dsc \
+ $conv_dir/chromium-src
+
+ local uc_rev="${uc_tag##*-}"
+ local ucd_convert=$GITHUB_WORKSPACE/convert
+
+ local ups_version="${deb_version%-*}"
+
+ # NOTE: Nested output groups are not yet supported
+ # https://github.com/actions/toolkit/issues/1001
+ #echo '::group::Ungoogling Chromium'
+
+ (cd $conv_dir && run $wrap make -f $ucd_convert/Makefile \
+ convert ug-tarball clean \
+ VERSION=$ups_version \
+ ORIG_SOURCE=chromium-src \
+ ORIG_TARBALL=$DOWNLOAD_DIR/chromium_$ups_version.orig.tar.xz \
+ UNGOOGLED=$uc_git \
+ DEBIAN_CONVERT=$ucd_convert \
+ ADD_VERSION_SUFFIX=.$uc_rev \
+ DISTRIBUTION= \
+ INPLACE=1
+ )
+
+ #echo '::endgroup::'
+
+ echo 'Building new source package ...'
+ (cd $conv_dir && run time -p dpkg-source --no-preparation --no-generate-diff --build chromium-src 2>&1)
+
+ local uc_version=$deb_version.$uc_rev
+
+ local files=
+ files="$codename/ungoogled-chromium_$uc_version.dsc"
+ files+=" $codename/ungoogled-chromium_$uc_version.debian.tar.xz"
+ ofiles=" $codename/ungoogled-chromium_$ups_version.orig.tar.xz"
+
+ mkdir -p $OUTPUT_DIR/$codename
+
+ (cd $conv_dir/..
+ ls -LUl $files $ofiles
+ echo ' '; echo 'SHA-256 sums:'
+ sha256sum $files $ofiles
+ cp -np $files $OUTPUT_DIR/$codename/
+ )
+
+ # Note: Do NOT save the .orig tarball as an artifact!
+ # It's enormous, and we do not modify it.
+
+ rm -rf $conv_dir
+}
+
+for todo in $WORK_DIR/todo.*.chromium.txt
+do
+ test -f "$todo" || continue
+ IFS="$tab" read codename deb_version uc_tag < $todo
+
+ echo "::group::Build DEB($codename, $deb_version) + UC($uc_tag)"
+
+ do_conversion "$codename" "$deb_version" "$uc_tag"
+
+ echo '::endgroup::'
+
+ case "$codename" in
+ debian-sid | debian-unstable)
+ # do Ubuntu conversions here if desired
+ ;;
+ esac
+
+ cat $todo >> $STATE_DIR/done.chromium.txt
+ rm -f $todo
+ echo ' '
+done
+
+# end convert.sh
diff --git a/.github/workflows/dpkg-source-build.patch b/.github/workflows/dpkg-source-build.patch
new file mode 100644
index 000000000..b829399c9
--- /dev/null
+++ b/.github/workflows/dpkg-source-build.patch
@@ -0,0 +1,99 @@
+This patch greatly speeds up the "dpkg-source --build" operation when the
+--no-generate-diff option is used. It has been submitted to the upstream
+project, but discussion on it remains unresolved:
+
+ https://lists.debian.org/debian-dpkg/2023/09/msg00013.html
+
+This patch specifically targets the version of dpkg in Ubuntu 22.04.
+
+--- /usr/share/perl5/Dpkg/Source/Package/V2.pm.orig
++++ /usr/share/perl5/Dpkg/Source/Package/V2.pm
+@@ -60,6 +60,7 @@
+ $self->{options}{unapply_patches} //= 'auto';
+ $self->{options}{skip_debianization} //= 0;
+ $self->{options}{create_empty_orig} //= 0;
++ $self->{options}{generate_diff} //= 1;
+ $self->{options}{auto_commit} //= 0;
+ $self->{options}{ignore_bad_version} //= 0;
+ }
+@@ -94,6 +95,10 @@
+ help => N_('create an empty original tarball if missing'),
+ when => 'build',
+ }, {
++ name => '--no-generate-diff',
++ help => N_('do not generate diff against upstream sources'),
++ when => 'build',
++ }, {
+ name => '--abort-on-upstream-changes',
+ help => N_('abort if generated diff has upstream files changes'),
+ when => 'build',
+@@ -145,6 +150,9 @@
+ } elsif ($opt eq '--create-empty-orig') {
+ $self->{options}{create_empty_orig} = 1;
+ return 1;
++ } elsif ($opt eq '--no-generate-diff') {
++ $self->{options}{generate_diff} = 0;
++ return 1;
+ } elsif ($opt eq '--abort-on-upstream-changes') {
+ $self->{options}{auto_commit} = 0;
+ return 1;
+@@ -448,6 +456,8 @@
+ }
+ }
+
++ return if !$opts{do_diff};
++
+ # Unpack a second copy for comparison
+ my $tmp = tempdir("$dirname.orig.XXXXXX", DIR => $updir);
+ push_exit_handler(sub { erasedir($tmp) });
+@@ -516,6 +526,21 @@
+ usageerr(g_("-b takes only one parameter with format '%s'"),
+ $self->{fields}{'Format'});
+ }
++ if (!$self->{options}{generate_diff} &&
++ ($self->{options}{include_removal} ||
++ $self->{options}{include_timestamp} ||
++ $self->{options}{include_binaries} ||
++ $self->{options}{create_empty_orig} ||
++ $self->{options}{auto_commit})) {
++ my @incompat = (
++ "--include-removal",
++ "--include-timestamp",
++ "--include-binaries",
++ "--create-empty-orig",
++ "--auto-commit"
++ );
++ usageerr(g_("--no-generate-diff is incompatible with the following options: %s"), join(", ", @incompat));
++ }
+ $self->prepare_build($dir);
+
+ my $include_binaries = $self->{options}{include_binaries};
+@@ -555,8 +580,9 @@
+ header_from => $autopatch,
+ handle_binary => $handle_binary,
+ skip_auto => $self->{options}{auto_commit},
++ do_diff => $self->{options}{generate_diff},
+ usage => 'build');
+- unless (-z $tmpdiff or $self->{options}{auto_commit}) {
++ unless (!$tmpdiff or -z $tmpdiff or $self->{options}{auto_commit}) {
+ info(g_('Hint: make sure the version in debian/changelog matches ' .
+ 'the unpacked source tree'));
+ info(g_('you can integrate the local changes with %s'),
+@@ -564,7 +590,7 @@
+ error(g_('aborting due to unexpected upstream changes, see %s'),
+ $tmpdiff);
+ }
+- push_exit_handler(sub { unlink($tmpdiff) });
++ push_exit_handler(sub { !$tmpdiff or unlink($tmpdiff) });
+ $binaryfiles->update_debian_source_include_binaries() if $include_binaries;
+
+ # Install the diff as the new autopatch
+@@ -576,7 +602,7 @@
+ $autopatch) if -e $autopatch;
+ rmdir(File::Spec->catdir($dir, 'debian', 'patches')); # No check on purpose
+ }
+- unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff);
++ !$tmpdiff or unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff);
+ pop_exit_handler();
+
+ # Create the debian.tar
diff --git a/.github/workflows/get-latest.sh b/.github/workflows/get-latest.sh
new file mode 100755
index 000000000..5e05b1b11
--- /dev/null
+++ b/.github/workflows/get-latest.sh
@@ -0,0 +1,213 @@
+#!/bin/bash
+# get-latest.sh
+#
+# Determine the latest version(s) of the "chromium" package in the Debian
+# repositories, download the corresponding source package(s), and look for
+# matching ungoogled-chromium Git release tags.
+#
+
+set -e
+
+test -n "$DOWNLOAD_DIR"
+test -n "$STATE_DIR"
+test -n "$WORK_DIR"
+test -d "$GITHUB_WORKSPACE"
+
+debian_codename_list='bookworm sid'
+
+package=chromium
+
+obsolete_list=$WORK_DIR/obsolete.$package.txt
+
+debian_incoming_url=https://incoming.debian.org/debian-buildd
+debian_security_url=https://security.debian.org/debian-security
+
+chdist_dir=$STATE_DIR/chdist-data
+chdist="chdist --data-dir=$chdist_dir"
+uc_git=$GITHUB_WORKSPACE/ungoogled-chromium
+
+tab=' '
+
+do_update=yes
+do_download=yes
+do_status=no
+
+todo_flag= # Note: "false" is interpreted by GitHub as true >_<
+
+export LC_COLLATE=C
+
+while [ -n "$1" ]
+do
+ case "$1" in
+ --skip-update) do_update=no ;;
+ --skip-download) do_download=no ;;
+ --exit-status) do_status=yes ;;
+ '') ;;
+ -*) echo "$0: error: unrecognized option \"$1\""; exit 1 ;;
+ *) echo "$0: error: unrecognized argument \"$1\""; exit 1 ;;
+ esac
+ shift
+done
+
+if [ ! -d $uc_git ]
+then
+ echo 'Error: ungoogled-chromium Git repository is not present'
+ exit 1
+fi
+
+run()
+{
+ echo "+ $*"
+ env "$@"
+ echo ' '
+}
+
+check_debian_release()
+{
+ local deb_codename="debian-$1"
+
+ # Latest version of the package in the APT repo
+ # (for the specified release, e.g. "unstable" or "bullseye")
+ local deb_version=$($chdist apt-get $deb_codename --print-uris source $package 2>/dev/null \
+ | awk '/\.dsc /{print $2}' \
+ | sed -r 's/^[^_]+_//; s/\.dsc$//')
+
+ if [ -n "$deb_version" ]
+ then
+ echo "$deb_codename/$package: current package version $deb_version"
+ else
+ # Note that Debian's incoming repo doesn't always have
+ # a given package available; this is not an error
+ echo "$deb_codename/$package: no version available"
+ echo ' '
+ return
+ fi
+
+ # Upstream project version (remove the package-revision suffix)
+ local ups_version="${deb_version%-*}"
+ if [ -z "$ups_version" ]
+ then
+ echo "error: package version string is bogus"
+ exit 1
+ fi
+
+ # Latest matching ungoogled-chromium tag
+ local uc_tag=$(cd $uc_git && git tag --list --sort=-version:refname "$ups_version-*" | head -n1)
+
+ if [ -n "$uc_tag" ]
+ then
+ echo "ungoogled-chromium: latest matching tag $uc_tag"
+ else
+ echo "ungoogled-chromium: no matching tag for $ups_version"
+ echo ' '
+ return
+ fi
+
+ local combo_line="$deb_codename$tab$deb_version$tab$uc_tag"
+
+ # Have we built this combination before?
+ if grep -Fqx "$combo_line" $STATE_DIR/done.$package.txt 2>/dev/null
+ then
+ echo "Already built DEB($deb_codename, $deb_version) + UC($uc_tag)"
+ echo ' '
+ return
+ else
+ echo "Will build DEB($deb_codename, $deb_version) + UC($uc_tag)"
+ fi
+
+ if [ $do_download = yes ]
+ then
+ echo ' '
+ echo "$deb_codename/$package: downloading source package files"
+
+ (cd $DOWNLOAD_DIR && run $chdist apt-get $deb_codename --quiet --only-source --download-only source $package)
+ fi
+
+ echo ' '
+
+ echo "$combo_line" > $WORK_DIR/todo.$deb_codename.$package.txt
+ todo_flag=true
+}
+
+find_obsolete_files()
+{
+ : > $obsolete_list
+
+ local keep_count=$(wc -w <<<$debian_codename_list)
+ local orig_file
+
+ # We should not need to hang on to more orig source tarballs than
+ # the number of codenames we are monitoring
+
+ (cd $DOWNLOAD_DIR && ls -1t ${package}_*.orig.tar.* 2>/dev/null) \
+ | tail -n +$((keep_count + 1)) \
+ | while read orig_file
+ do
+ local prefix=${orig_file%.orig.tar.*}
+
+ (cd $DOWNLOAD_DIR && ls -1 $orig_file $prefix-*.dsc $prefix-*.debian.tar.*) \
+ >> $obsolete_list
+ done
+}
+
+#
+# First-time setup
+#
+
+mkdir -p $DOWNLOAD_DIR $STATE_DIR $chdist_dir
+new_apt=no
+
+for codename in $debian_codename_list
+do
+ deb_codename=debian-$codename
+ test ! -d $chdist_dir/$deb_codename || continue
+ echo "Initializing APT index for $deb_codename ..."
+
+ case "$deb_codename" in
+ debian-sid | debian-unstable)
+ run $chdist create $deb_codename $debian_incoming_url buildd-$codename main
+ ;;
+
+ *)
+ run $chdist create $deb_codename $debian_security_url $codename-security main
+ ;;
+ esac
+
+ new_apt=yes
+done
+
+if [ $new_apt = yes ]
+then
+ # We only need deb-src lines, no binary packages
+ find $chdist_dir -type f -name sources.list \
+ -exec sed -i '/^deb /s/^/#/' {} +
+fi
+
+#
+# Do version checks
+#
+
+for codename in $debian_codename_list
+do
+ deb_codename=debian-$codename
+
+ if [ $do_update = yes ]
+ then
+ echo "Updating APT index for $deb_codename ..."
+ run $chdist apt-get $deb_codename update --error-on=any
+ fi
+
+ check_debian_release $codename
+done
+
+find_obsolete_files
+
+if [ -n "$GITHUB_OUTPUT" ]
+then
+ echo todo=$todo_flag >> $GITHUB_OUTPUT
+fi
+
+test $do_status = no || test $todo_flag = true || exit 1
+exit 0
+
+# end get-latest.sh
diff --git a/.github/workflows/obs-upload.sh b/.github/workflows/obs-upload.sh
index 880268ffc..18190ed6d 100755
--- a/.github/workflows/obs-upload.sh
+++ b/.github/workflows/obs-upload.sh
@@ -1,136 +1,199 @@
-#!/bin/sh
+#!/bin/bash
+# obs-upload.sh
+#
+# Upload Debian source package files to the openSUSE Build Service
+# (https://build.opensuse.org/)
+#
+
set -e
-RT_DIR="$PWD"
-DB_DIR="$RT_DIR/debian"
-UC_DIR="$DB_DIR/submodules/ungoogled-chromium"
+test -n "$DOWNLOAD_DIR"
+test -n "$OUTPUT_DIR"
+test -n "$WORK_DIR"
+
+upload_dir=$WORK_DIR/upload
-for i in OBS_API_USERNAME OBS_API_PASSWORD
+for var in OSC_USERNAME OSC_PASSWORD
do
- if test -z "$(eval echo \$$i)"
- then
- echo "$i is not in the environment. Aborting."
- exit 1
- fi
+ if test -z "$(eval echo \$$var)"
+ then
+ echo "$var is not set in the environment. Aborting."
+ exit 1
+ fi
done
-PROJECT="${OBS_API_PROJECT:-home:$OBS_API_USERNAME}"
+test -n "$OSC" || OSC=osc
+test -n "$OBS_PROJECT" || export OBS_PROJECT="home:$OSC_USERNAME"
+
+# Do NOT use a config file, just rely on the env vars
+#
+export OSC_CONFIG=/dev/null
-case "$GITHUB_EVENT_NAME" in
- workflow_dispatch) REPOSITORY="$PROJECT:testing" ;;
- push) REPOSITORY="$PROJECT" ;;
- *) echo "Not running as part of a GitHub workflow. Aborting."; exit 1 ;;
-esac
+if ! $OSC --help > /dev/null 2>&1
+then
+ echo 'osc(1) is not available. Aborting.'
+ exit 1
+fi
-curl()
+# API reference: https://api.opensuse.org/apidocs/
+
+osc_add_file()
{
- for i in `seq 1 5`
- do
- {
- command curl -sS -K - "$@" << EOF
-user="$OBS_API_USERNAME:$OBS_API_PASSWORD"
-EOF
- } && return 0 || sleep 30s
- done
- return 1
+ local project="$1" package="$2" local_file="$3" remote_file="$4"
+ test -n "$remote_file" || remote_file="$local_file"
+
+ $OSC api -T "$local_file" "/source/$project/$package/$remote_file" > /dev/null
}
-debian/rules changelog control
+osc_delete_file()
+{
+ local project="$1" package="$2" file="$3"
+
+ $OSC api -X DELETE "/source/$project/$package/$file" > /dev/null
+}
-read UC_VERSION < $UC_DIR/chromium_version.txt
-AUTHOR=`grep 'AUTHOR *:=' $DB_DIR/rules | cut -f 2 -d '=' | sed -r 's;^ *| *$;;g'`
-NODE_VERSION=`grep 'NODE_VERSION *:=' $DB_DIR/rules | cut -f 2 -d '=' | sed -r 's;^ *| *$;;g'`
+osc_commit()
+{
+ local project="$1" package="$2" comment="$3"
+ local comment_enc=$(printf '%s' "$comment" | jq -Rrs @uri)
+
+ # Note: The regular "osc commit" command requires a checked-out
+ # package directory, and is thus not suitable for our use here
+
+ $OSC api -m POST "/source/$project/$package?cmd=commit&comment=$comment_enc" > /dev/null
+}
+
+obs_sync_files()
+{
+ local codename="$1" dir="$2" commit_message="$3"
+ local remote_list=$WORK_DIR/remote-files.txt
+
+ echo "Syncing files to OBS project/package: $OBS_PROJECT/$codename"
+
+ $OSC list -l $OBS_PROJECT $codename > $remote_list
+
+ (cd $dir
+
+ do_commit=false
+
+ while read md5 rev size d1 d2 d3 remote_file
+ do
+ if [ ! -f "$remote_file" ]
+ then
+ echo "D $codename/$remote_file ..."
+ osc_delete_file $OBS_PROJECT $codename "$remote_file"
+ do_commit=true
+ fi
+ done < $remote_list
+
+ for local_file in *
+ do
+ do_upload=false
+
+ if awk -v file="$local_file" \
+ '$7 == file {print "found"}' $remote_list \
+ | grep -q .
+ then
+ # File present on OBS, check MD5 sum
+ md5=$(md5sum "$local_file" | awk '{print $1}')
+ awk \
+ -v md5="$md5" \
+ -v file="$local_file" \
+ '$1 == md5 && $7 == file {print "found"}' \
+ $remote_list \
+ | grep -q . || do_upload=true
+ else
+ # File not present on OBS
+ do_upload=true
+ fi
+
+ if $do_upload
+ then
+ echo "A $codename/$local_file ..."
+ osc_add_file $OBS_PROJECT $codename "$local_file"
+ do_commit=true
+ fi
+ done
+
+ if $do_commit
+ then
+ echo 'Committing update ...'
+ osc_commit $OBS_PROJECT $codename "$commit_message"
+ else
+ echo 'No changes to commit.'
+ fi
+
+ ) # return to previous dir
+
+ rm -f $remote_list
+}
+
+for dsc_file in $OUTPUT_DIR/*/*.dsc
+do
+ dir=$(dirname $dsc_file)
+ codename=$(basename $dir)
-cat > _service << EOF
+ package=$(sed -n 's/^Source: //p' $dsc_file)
+ version=$(sed -n 's/^Version: //p' $dsc_file)
+
+ sums=$(grep -E '^ [0-9a-f]{64} ' $dsc_file)
+
+ orig_src=$(echo "$sums" | awk '/\.orig\.tar\./ {print $3}')
+ debian_src=$(echo "$sums" | awk '/\.debian\.tar\./ {print $3}')
+
+ dsc_sha256=$(sha256sum $dsc_file | awk '{print $1}')
+
+ orig_src_sha256=$(echo "$sums" | awk '/\.orig\.tar\./ {print $1}')
+ debian_src_sha256=$(echo "$sums" | awk '/\.debian\.tar\./ {print $1}')
+
+ chromium_orig_src=$DOWNLOAD_DIR/${orig_src#ungoogled-}
+ test -s $chromium_orig_src
+
+ run_url=
+ test -z "$GITHUB_RUN_ID" || run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
+
+ if [ -n "$run_url" ]
+ then
+ comment="Origin: $run_url"
+ else
+ comment="Origin: manual upload"
+ fi
+
+ rm -rf $upload_dir
+ mkdir -p $upload_dir
+
+ ln $dsc_file $dir/$debian_src $upload_dir/
+ ln $chromium_orig_src $upload_dir/$orig_src
+
+ # Reference: https://en.opensuse.org/openSUSE:Build_Service_Concept_SourceService
+ #
+ cat > $upload_dir/_service << END
+
-
- https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$UC_VERSION.tar.xz
-
-
- https://commondatastorage.googleapis.com/chromium-browser-official/chromium-$UC_VERSION.tar.xz.hashes
-
-
- https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-x64.tar.xz
-
-
- https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-armv7l.tar.xz
-
-
- https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-linux-arm64.tar.xz
-
-
- https://nodejs.org/dist/$NODE_VERSION/SHASUMS256.txt
- node-$NODE_VERSION.sha256sum
-
+
+ $orig_src
+ sha256
+ $orig_src_sha256
+
+
+ $debian_src
+ sha256
+ $debian_src_sha256
+
+
+ $(basename $dsc_file)
+ sha256
+ $dsc_sha256
+
-EOF
-
-tar -c -T/dev/null | xz -9 > ungoogled-chromium_$UC_VERSION.orig.tar.xz
-tar -c -T/dev/null | xz -9 > ungoogled-chromium_$UC_VERSION.debian.tar.xz
-tar -c --exclude-vcs --exclude='download_cache/*' -C $RT_DIR debian/ | xz -9 > ungoogled-chromium.tar.xz
-
-cat > ungoogled-chromium.dsc << EOF
-Format: 3.0 (quilt)
-Source: ungoogled-chromium
-Binary: ungoogled-chromium
-Architecture: any
-Version: $UC_VERSION
-Maintainer: $AUTHOR
-Homepage: https://github.com/Eloston/ungoogled-chromium
-Standards-Version: 4.5.0
-Build-Depends: $(sed -n '/^Build-Depends:/,/^$/p' < $DB_DIR/control | tr -d '\n' | cut -f 2 -d : | sed -r 's;^ *| *$;;g')
-Package-List:
- ungoogled-chromium deb web optional arch=any
-Checksums-Sha1:
- $(sha1sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz
- $(sha1sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz
-Checksums-Sha256:
- $(sha256sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz
- $(sha256sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz
-Files:
- $(md5sum < ungoogled-chromium_$UC_VERSION.orig.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.orig.tar.xz) ungoogled-chromium_$UC_VERSION.orig.tar.xz
- $(md5sum < ungoogled-chromium_$UC_VERSION.debian.tar.xz | cut -f 1 -d ' ') $(stat -c '%s' ungoogled-chromium_$UC_VERSION.debian.tar.xz) ungoogled-chromium_$UC_VERSION.debian.tar.xz
-EOF
-
-cat > build.script << EOF
-export LANG=C.UTF-8
-
-JOBS="\${DEB_BUILD_OPTIONS#*=}"
-case "\$(uname -m)" in
-aarch64) DEB_BUILD_OPTIONS="parallel=\$(("\$JOBS" / 2))" ;;
-esac
-JOBS=
-
-tar -x -f ../SOURCES/ungoogled-chromium.tar.xz
-mkdir -p debian/download_cache
-ln -s ../../../SOURCES/chromium-$UC_VERSION.tar.xz debian/download_cache/chromium-$UC_VERSION.tar.xz
-ln -s ../../../SOURCES/chromium-$UC_VERSION.tar.xz.hashes debian/download_cache/chromium-$UC_VERSION.tar.xz.hashes
-ln -s ../../../SOURCES/node-$NODE_VERSION-linux-x64.tar.xz debian/download_cache/node-$NODE_VERSION-linux-x64.tar.xz
-ln -s ../../../SOURCES/node-$NODE_VERSION-linux-armv7l.tar.xz debian/download_cache/node-$NODE_VERSION-linux-armv7l.tar.xz
-ln -s ../../../SOURCES/node-$NODE_VERSION-linux-arm64.tar.xz debian/download_cache/node-$NODE_VERSION-linux-arm64.tar.xz
-ln -s ../../../SOURCES/node-$NODE_VERSION.sha256sum debian/download_cache/node-$NODE_VERSION.sha256sum
-
-debian/rules setup
-
-dpkg-buildpackage -b -uc
-EOF
-
-PACKAGE="ungoogled-chromium-debian"
-
-curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" -F 'cmd=deleteuploadrev'
-
-curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" > directory.xml
-
-xmlstarlet sel -t -v '//entry/@name' < directory.xml | while read FILENAME
-do
- curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE/$FILENAME?rev=upload" -X DELETE
-done
+END
-for FILENAME in _service ungoogled-chromium_$UC_VERSION.orig.tar.xz ungoogled-chromium_$UC_VERSION.debian.tar.xz ungoogled-chromium.tar.xz ungoogled-chromium.dsc build.script
-do
- curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE/$FILENAME?rev=upload" -T "$FILENAME"
-done
+ commit_message="$package $version
-curl "https://api.opensuse.org/source/$REPOSITORY/$PACKAGE" -F 'cmd=commit'
+$comment"
+
+ obs_sync_files $codename $upload_dir "$commit_message"
+ echo ' '
+done
-rm -f _service ungoogled-chromium_$UC_VERSION.orig.tar.xz ungoogled-chromium_$UC_VERSION.debian.tar.xz ungoogled-chromium.tar.xz ungoogled-chromium.dsc build.script directory.xml
+# end obs-upload.sh
diff --git a/.github/workflows/obs-upload.yml b/.github/workflows/obs-upload.yml
deleted file mode 100644
index 484537858..000000000
--- a/.github/workflows/obs-upload.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-name: OBS Upload
-
-on:
- workflow_dispatch:
- push:
- tags:
- - '*'
-
-jobs:
- obs-upload:
- runs-on: ubuntu-latest
- steps:
- - uses: styfle/cancel-workflow-action@0.10.0
- with:
- access_token: ${{ github.token }}
- - uses: actions/checkout@v3
- - name: Convert from shallow repository to full repository
- run: git fetch --unshallow
- - name: Initialize submodules
- run: git submodule update --init --recursive
- - name: Install extra packages
- run: sudo apt install -y xmlstarlet
- - name: Run OBS Upload Script
- env:
- OBS_API_USERNAME: ${{ secrets.OBS_API_USERNAME }}
- OBS_API_PASSWORD: ${{ secrets.OBS_API_PASSWORD }}
- OBS_API_PROJECT: ${{ secrets.OBS_API_PROJECT }}
- run: .github/workflows/obs-upload.sh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 000000000..a426ba826
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,144 @@
+---
+name: Release cycle
+
+on:
+ repository_dispatch:
+ types: [new-debian-version, new-uc-version]
+ workflow_dispatch:
+
+concurrency:
+ group: __ungoogled-chromium_singleton__
+
+jobs:
+ main:
+ runs-on: ubuntu-latest
+ permissions:
+ # needed by "gh cache delete"
+ actions: write
+ env:
+ DOWNLOAD_DIR: /home/runner/download
+ OUTPUT_DIR: /home/runner/output
+ STATE_DIR: /home/runner/state
+ WORK_DIR: /home/runner/work
+ steps:
+ - name: Clone u-c-d Git repository
+ uses: actions/checkout@v4
+
+ - name: Clone u-c Git repository
+ uses: actions/checkout@v4
+ with:
+ repository: ungoogled-software/ungoogled-chromium
+ fetch-depth: 20
+ fetch-tags: true
+ path: ungoogled-chromium
+
+ - name: Tweak Dpkg config to elide progress indicators
+ run: echo 'Dpkg::Use-Pty "false";' | sudo tee /etc/apt/apt.conf.d/55no-use-pty
+
+ - name: Install packages required for upstream check
+ run: sudo apt-get -y --no-install-recommends install debian-archive-keyring devscripts
+
+ - name: Restore persistent state
+ id: restore-state
+ uses: actions/cache/restore@v4
+ # https://github.com/actions/runner/discussions/871
+ with:
+ key: state-v${{github.run_id}}
+ restore-keys: state
+ path: ${{env.STATE_DIR}}
+
+ - name: Check if new upstream versions are available
+ id: check
+ run: .github/workflows/get-latest.sh --skip-download
+
+ - name: Restore download cache
+ id: restore-download
+ if: ${{steps.check.outputs.todo}}
+ uses: actions/cache/restore@v4
+ # https://github.com/actions/runner/discussions/871
+ with:
+ key: download-v${{github.run_id}}
+ restore-keys: download
+ path: ${{env.DOWNLOAD_DIR}}
+
+ - name: Download latest upstream versions
+ if: ${{steps.check.outputs.todo}}
+ run: .github/workflows/get-latest.sh --skip-update
+
+ - name: Remove obsolete files from download cache
+ if: ${{steps.check.outputs.todo}}
+ run: |
+ del_files=$(cat $WORK_DIR/obsolete.chromium.txt)
+ cd $DOWNLOAD_DIR
+ rm -fv $del_files
+ echo 'Download cache contents:'
+ ls -l
+
+ - name: Save download cache
+ if: ${{steps.check.outputs.todo}}
+ uses: actions/cache/save@v4
+ with:
+ key: download-v${{github.run_id}}
+ path: ${{env.DOWNLOAD_DIR}}
+
+ - name: Delete previous version of download cache
+ if: ${{steps.check.outputs.todo && steps.restore-download.outputs.cache-matched-key}}
+ env:
+ GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: gh cache delete ${{steps.restore-download.outputs.cache-matched-key}}
+
+ - name: Install packages required for conversion
+ if: ${{steps.check.outputs.todo}}
+ run: sudo apt-get -y --no-install-recommends install debian-keyring dpkg-dev quilt
+
+ - name: Patch Dpkg to speed up source package builds
+ if: ${{steps.check.outputs.todo}}
+ run: (cd / && sudo patch -p1) < .github/workflows/dpkg-source-build.patch
+
+ - name: Clone osc Git repository
+ # Needed because the version of osc(1) in ubuntu-22.04 is too old
+ if: ${{steps.check.outputs.todo}}
+ uses: actions/checkout@v4
+ with:
+ repository: openSUSE/osc
+ ref: 21c9828cd1fc51b8d03f0f1aa01c41df38a3630b # 1.8.3
+ path: osc
+
+ - name: Convert chromium to ungoogled-chromium
+ if: ${{steps.check.outputs.todo}}
+ env:
+ DEBFULLNAME: ${{vars.DEBFULLNAME}}
+ DEBEMAIL: ${{vars.DEBEMAIL}}
+ run: .github/workflows/convert.sh
+
+ - name: Upload u-c packages to OBS
+ if: ${{steps.check.outputs.todo}}
+ env:
+ OSC: ${{github.workspace}}/osc/osc-wrapper.py
+ OSC_USERNAME: ${{secrets.OSC_USERNAME || vars.OSC_USERNAME}}
+ OSC_PASSWORD: ${{secrets.OSC_PASSWORD}}
+ OBS_PROJECT: ${{vars.OBS_PROJECT}}
+ run: .github/workflows/obs-upload.sh
+
+ - name: Save persistent state
+ uses: actions/cache/save@v4
+ with:
+ key: state-v${{github.run_id}}
+ path: ${{env.STATE_DIR}}
+
+ - name: Delete previous version of persistent state
+ if: ${{steps.restore-state.outputs.cache-matched-key}}
+ env:
+ GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
+ run: gh cache delete ${{steps.restore-state.outputs.cache-matched-key}}
+
+ - name: Save converted source package files as artifacts
+ if: ${{steps.check.outputs.todo}}
+ uses: actions/upload-artifact@v4
+ with:
+ name: releases
+ compression-level: 1
+ if-no-files-found: ignore
+ path: ${{env.OUTPUT_DIR}}/*
+
+# EOF
diff --git a/.github/workflows/remote-check.sh b/.github/workflows/remote-check.sh
new file mode 100755
index 000000000..b9bfc6288
--- /dev/null
+++ b/.github/workflows/remote-check.sh
@@ -0,0 +1,200 @@
+#!/bin/bash
+#
+# Check for new "chromium" package(s) on Debian without all the overhead of
+# the GitHub workflow. This script can be invoked from cron(8), from a mail
+# delivery agent (e.g. maildrop(1)), or directly.
+#
+# Recommended crontab entry:
+#
+# 15 */4 * * * /path/to/remote-check.sh --cron
+#
+# Mail invocation is intended for use with the Debian package tracker at
+# https://tracker.debian.org/ . Create an account with your e-mail address,
+# and subscribe to the "chromium" source package, with the "upload-source"
+# keyword. Configure your MDA to match on messages with the following
+# header fields:
+#
+# From: Debian FTP Masters
+# Subject: Accepted chromium *** (source) into ***
+#
+# (where "***" is a short string match, like a /.+/ regex. You can see past
+# instances of these messages under the "news" section at the tracker's
+# Chromium page: https://tracker.debian.org/pkg/chromium)
+#
+# Then, have it execute this script as
+#
+# /path/to/remote-check.sh --mail
+#
+# To invoke the GitHub workflow, you'll need to create a "fine-grained
+# personal access token" here:
+#
+# https://github.com/settings/tokens?type=beta
+#
+# Under "Repository access", specify the ungoogled-chromium-debian repo,
+# and under "Repository permissions -> Contents", grant "read and write"
+# access. Then place the token string in a file token.txt in the state
+# directory (see below).
+#
+# You can invoke the workflow directly with "remote-check.sh --start".
+#
+
+state_dir=$HOME/.cache/uc-remote-check
+github_repo=ungoogled-software/ungoogled-chromium-debian
+
+debian_incoming_url=https://incoming.debian.org/debian-buildd
+debian_security_url=https://security.debian.org/debian-security
+
+common_curl_args="--hsts $state_dir/curl-hsts.txt --max-time 30 --no-progress-meter"
+
+log()
+{
+ local message="$1"
+ local dt=$(date --rfc-3339=sec)
+ echo "[$dt]${message:+ $message}"
+}
+
+start_workflow()
+{
+ local github_token=$(cat $state_dir/token.txt 2>/dev/null)
+
+ case "$github_token" in
+ github_pat_*) ;;
+ '') echo 'Cannot start workflow, no GitHub token present'; return 0 ;;
+ *) echo 'Error: Invalid GitHub token'; return 2 ;;
+ esac
+
+ log "Starting release workflow at $github_repo"
+
+ local headers_file=$state_dir/tmp.headers.txt
+
+ (umask 077; cat > $headers_file) << END
+Accept: application/vnd.github+json
+Authorization: token $github_token
+END
+
+ curl \
+ --header @$headers_file \
+ --data '{"event_type": "new-debian-version"}' \
+ --fail-with-body \
+ $common_curl_args \
+ https://api.github.com/repos/$github_repo/dispatches
+}
+
+do_check()
+{
+ local hash_dsc_file=$state_dir/debian-hash-dsc.txt
+ local seen_dsc_file=$state_dir/debian-seen-dsc.txt
+
+ local index=$state_dir/tmp.index-1.txt
+ local index_concat=$state_dir/tmp.index-2.txt
+ local new_dsc_file=$state_dir/tmp.new-dsc.txt
+
+ log 'Checking Debian servers ...'
+
+ : > $index_concat
+ : > $new_dsc_file
+
+ local url
+ for url in \
+ $debian_incoming_url \
+ $debian_security_url
+ do
+ curl \
+ --output $index \
+ --compressed \
+ --fail \
+ $common_curl_args \
+ $url/pool/main/c/chromium/
+
+ # Note: The "incoming" server may return a 404 when no
+ # recent package release is available
+
+ cat $index >> $index_concat 2>/dev/null
+ done
+
+ # First-level check
+
+ local dsc_hash=$(grep -F .dsc $index_concat | md5sum | awk '{print $1}')
+ local prev_dsc_hash=$(cat $hash_dsc_file 2>/dev/null)
+
+ if [ "_$dsc_hash" = "_$prev_dsc_hash" ]
+ then
+ echo 'No change in available .dsc files'
+ return 1
+ fi
+
+ # Second-level check
+
+ grep -Eo ' href="[^ "]+\.dsc"' $index_concat \
+ | cut -d'"' -f2 \
+ | while read dsc
+ do
+ if ! grep -Fqx "$dsc" $seen_dsc_file 2>/dev/null
+ then
+ echo "Found new .dsc file: $dsc"
+ echo "$dsc" >> $new_dsc_file
+ fi
+ done
+
+ if [ ! -s $new_dsc_file ]
+ then
+ echo 'No new .dsc file(s) found'
+ rm -f $new_dsc_file
+ return 1
+ fi
+
+ # New release found
+
+ if [ -f $seen_dsc_file ]
+ then
+ start_workflow || return
+ else
+ echo 'Initial run, not starting workflow'
+ fi
+
+ cat $new_dsc_file >> $seen_dsc_file
+ echo $dsc_hash > $hash_dsc_file
+
+ rm -f $new_dsc_file
+}
+
+from_cron=false
+from_mail=false
+start=false
+
+case "$1" in
+ --cron) from_cron=true ;;
+ --mail) from_mail=true ;;
+ --start) start=true ;;
+esac
+
+mkdir -p $state_dir || exit
+tty -s || exec >> $state_dir/log.txt 2>&1
+
+if $from_cron
+then
+ sleep_time=$((RANDOM % 300))
+ log "Started from cron, waiting $sleep_time seconds ..."
+ sleep $sleep_time
+ do_check
+elif $from_mail
+then
+ log 'Started by mail message'
+ for try in $(seq 1 20)
+ do
+ ! do_check || break
+ sleep_time=$((90 + RANDOM % 30))
+ log "Waiting $sleep_time seconds ..."
+ sleep $sleep_time
+ done
+elif $start
+then
+ start_workflow
+else
+ do_check
+fi
+
+rm -f $state_dir/tmp.*
+echo
+
+# EOF